Using a Vec<u8> to mock file Write - vector

My function signature is:
fn write_header(source_pkey: PublicKey, target_pkey: PublicKey, nonce: Nonce,
mut output: &mut Box<&mut dyn Write>) -> anyhow::Result<()> {
I'm trying to test it by using a Vec<u8> to mock a file:
#[test]
fn test_write_header() {
let mut vec = Vec::<u8>::new();
let mut out = Box::new(&mut vec);
write_header(
PublicKey([1u8; 32]),
PublicKey([2u8; 32]),
Nonce([3u8; 24]),
&mut out
).unwrap();
assert_eq!(out.len(), 104);
}
but I get the error:
error[E0308]: mismatched types
--> src/encrypt.rs:45:13
|
45 | &mut out
| ^^^^^^^^ expected trait object `dyn std::io::Write`, found struct `Vec`
|
= note: expected mutable reference `&mut Box<&mut dyn std::io::Write>`
found mutable reference `&mut Box<&mut Vec<u8>>
I am using dyn std::io::Write as I need this function to accept both File and Stdout in normal operation, as well as Vec<u8> for testing.
Am I doing this all wrong, or is it a matter of convincing the compiler that Vec<u8> has the Write trait?
Update:
The Box is because this code wouldn't compile without it, due to Sized issues.
/// Open the program's output file, or stdout if there is no input file.
/// Note: stdout on Windows only accepts utf8.
pub fn open_output(output: Option<String>) -> anyhow::Result<Box<dyn Write>> {
if let Some(filename) = output {
Ok(Box::new(File::open(&filename)
.context(format!("unable to open '{filename}' for output"))?))
} else {
Ok(Box::new(stdout()))
}
}
Is there a way to remove this Box? (Apologies for a follow-on question.)

As per #FrancisGagne comments, you can use directly &mut dyn Write, and then pass a &mut vec:
use anyhow; // 1.0.52
use std::io::Write;
fn write_header(
source_pkey: (),
target_pkey: (),
nonce: (),
mut output: &mut dyn Write,
) -> anyhow::Result<()> {
output.write(&[1])?;
anyhow::Ok(())
}
#[test]
fn test_write_header() {
let mut vec = Vec::<u8>::new();
write_header(
(),
(),
(),
&mut vec
).unwrap();
assert_eq!(vec.len(), 1);
}
Playground
Also you can use impl Write as the input parameter. This is neat, since you actually can make your function work for anything that implements Write itself:
fn write_header(
source_pkey: (),
target_pkey: (),
nonce: (),
mut output: impl Write,
) -> anyhow::Result<()> {
output.write(&[1])?;
anyhow::Ok(())
}
Playground

The solution was to keep the Box at the top level, as main() does not know whether output is a Stdout, a File or something else.
I've changed write_header's signature to:
fn write_header(source_pkey: PublicKey, target_pkey: PublicKey, nonce: Nonce,
output: &mut dyn Write) -> anyhow::Result<()> {
at Fracis Gagné's suggestion, which fixes the original issue.

Related

Declaring Associated Type of Trait Object in Async Function Parameter

I'd like a function which asynchronously processes a variable amount of (Sink, Stream) tuples.
use futures::channel::mpsc;
use futures::{Sink, Stream, SinkExt, StreamExt};
async fn foo(v: Vec<(Box<dyn Sink<Error = std::io::Error>>, Box<dyn Stream<Item = u8>>)>) {
for (mut tx, mut rx) in v {
let _ = tx.send(0);
let _ = rx.next().await;
}
}
#[tokio::main]
pub async fn main() -> Result<(), Box<dyn std::error::Error>> {
let (tx, mut rx) = mpsc::channel(32);
foo(vec![(Box::new(tx), Box::new(rx))]).await;
Ok(())
}
But I get this compilation error:
error[E0107]: wrong number of type arguments: expected 1, found 0
--> src/main.rs:4:30
|
4 | async fn foo(v: Vec<(Box<dyn Sink<Error = std::io::Error>>, Box<dyn Stream<Item = u8>>)>) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected 1 type argument
I was prompted to declare the associated type for the trait object that way by the compiler itself. I'm unsure why it does not accept it.
The compiler wants you to specify the "type argument" of the Sink. This is not the error type, but the type of the item being sent down the sink, as in Sink<Foo>. You specify u8 as the type of the stream, and are sending the value unchanged between one and the other, so you probably want a Sink<u8>.
Once you do that, the compiler will next complain that you need to specify the Error associated type (this time for real). However if you specify std::io::Error, the call to foo() from main() won't compile because the implementation of Sink for mpsc::Sender specifies its own mpsc::SendError as the error type.
Finally, both the sink and the stream need to be pinned so they can live across await points. This is done by using Pin<Box<...>> instead of Box<...> and Box::pin(...) instead of Box::new(...).
With the above changes, a version that compiles looks like this:
use futures::channel::mpsc;
use futures::{Sink, SinkExt, Stream, StreamExt};
use std::pin::Pin;
async fn foo(
v: Vec<(
Pin<Box<dyn Sink<u8, Error = mpsc::SendError>>>,
Pin<Box<dyn Stream<Item = u8>>>,
)>,
) {
for (mut tx, mut rx) in v {
let _ = tx.send(0);
let _ = rx.next().await;
}
}
#[tokio::main]
pub async fn main() -> Result<(), Box<dyn std::error::Error>> {
let (tx, rx) = mpsc::channel(32);
foo(vec![(Box::pin(tx), Box::pin(rx))]).await;
Ok(())
}

How to convert Vec<Item> to Vec<String>?

I have the following object, and trying to convert Vec<Courses> and retrieve CourseName.
pub struct Schools {
pub courses: Vec<CourseName>,
}
pub struct CourseName(String);
impl CourseName {
pub fn as_str(&self) -> &str {
&self.0[..]
}
}
Trying to get the Vec<String>, but my following approach does not work,
assigned_courses:Vec<String> = courses.iter().map(|c| c.clone().as_str()).collect()
getting the following error:
value of type `Vec<std::string::String>` cannot be built from `std::iter::Iterator<Item=&str>`
Update:
The map closure receives a &CourseName so clone just copies the reference. What you instead want is to access the tuple and clone the inner String with c.0.
let assigned_courses: Vec<String> = courses.iter().map(|c| c.0.clone()).collect();
Alternatively, if references to the course names are enough, then instead you can use as_str on the inner String.
let assigned_courses: Vec<&str> = schools.courses.iter().map(|c| c.0.as_str()).collect();
To fix the "private field" error. You can add a visibility modifier, e.g.
pub struct CourseName(pub String);
However, it's probably better to keep it as private, and instead add a method like as_str().
impl CourseName {
pub fn as_str(&self) -> &str {
&self.0
}
}
Then resulting in:
let assigned_courses: Vec<String> = schools.courses.iter().map(|c| c.as_str().to_string()).collect();
Alternatively, you could also impl AsRef<str> and/or Display for CourseName, to make everything more generalized.
Assuming that CourseName is just to have a typed version instead of a String. Then you could instead impl Display for CourseName.
use std::fmt;
pub struct CourseName(String);
impl fmt::Display for CourseName {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.0)
}
}
This allows you to do println!("{}, course") along with course.to_string().
let assigned_courses: Vec<String> = schools.courses.iter().map(|c| c.to_string()).collect();
Working example:
#[derive(Debug)]
pub struct CourseName(pub String);
fn courses_to_strings(list: &[CourseName]) -> Vec<String> {
list.iter().map(|course| course.0.clone()).collect()
}
fn main() {
let courses: Vec<CourseName> = vec![
CourseName("a".to_string()),
CourseName("b".to_string())
];
let strings = courses_to_strings(&courses);
dbg!(strings);
}
playground
All you needed to do was clone the String instead of the CourseName tuple struct in your map function, and also add the pub visibility modifier to the internal String.

How to implement a Future or Stream that polls an async fn?

I have a struct Test I want to implement std::future::Future that would poll function:
use std::{
future::Future,
pin::Pin,
task::{Context, Poll},
};
struct Test;
impl Test {
async fn function(&mut self) {}
}
impl Future for Test {
type Output = ();
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
match self.function() {
Poll::Pending => Poll::Pending,
Poll::Ready(_) => Poll::Ready(()),
}
}
}
That didn't work:
error[E0308]: mismatched types
--> src/lib.rs:17:13
|
10 | async fn function(&mut self) {}
| - the `Output` of this `async fn`'s expected opaque type
...
17 | Poll::Pending => Poll::Pending,
| ^^^^^^^^^^^^^ expected opaque type, found enum `Poll`
|
= note: expected opaque type `impl Future`
found enum `Poll<_>`
error[E0308]: mismatched types
--> src/lib.rs:18:13
|
10 | async fn function(&mut self) {}
| - the `Output` of this `async fn`'s expected opaque type
...
18 | Poll::Ready(_) => Poll::Ready(()),
| ^^^^^^^^^^^^^^ expected opaque type, found enum `Poll`
|
= note: expected opaque type `impl Future`
found enum `Poll<_>`
I understand that function must be called once, the returned Future must be stored somewhere in the struct, and then the saved future must be polled. I tried this:
struct Test(Option<Box<Pin<dyn Future<Output = ()>>>>);
impl Test {
async fn function(&mut self) {}
fn new() -> Self {
let mut s = Self(None);
s.0 = Some(Box::pin(s.function()));
s
}
}
That also didn't work:
error[E0277]: the size for values of type `(dyn Future<Output = ()> + 'static)` cannot be known at compilation time
--> src/lib.rs:7:13
|
7 | struct Test(Option<Box<Pin<dyn Future<Output = ()>>>>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `(dyn Future<Output = ()> + 'static)`
After I call function() I have taken a &mut reference of Test, because of that I can't change the Test variable, and therefore can't store the returned Future inside the Test.
I did get an unsafe solution (inspired by this)
struct Test<'a>(Option<BoxFuture<'a, ()>>);
impl Test<'_> {
async fn function(&mut self) {
println!("I'm alive!");
}
fn new() -> Self {
let mut s = Self(None);
s.0 = Some(unsafe { &mut *(&mut s as *mut Self) }.function().boxed());
s
}
}
impl Future for Test<'_> {
type Output = ();
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
self.0.as_mut().unwrap().poll_unpin(cx)
}
}
I hope that there is another way.
Though there are times when you may want to do things similar to what you're trying to accomplish here, they are a rarity. So most people reading this, maybe even OP, may wish to restructure such that struct state and data used for a single async execution are different objects.
To answer your question, yes it is somewhat possible. Unless you want to absolutely resort to unsafe code you will need to use Mutex and Arc. All fields you wish to manipulate inside the async fn will have to be wrapped inside a Mutex and the function itself will accept an Arc<Self>.
I must stress, however, that this is not a beautiful solution and you probably don't want to do this. Depending on your specific case your solution may vary, but my guess of what OP is trying to accomplish while using Streams would be better solved by something similar to this gist that I wrote.
use std::{
future::Future,
pin::Pin,
sync::{Arc, Mutex},
};
struct Test {
state: Mutex<Option<Pin<Box<dyn Future<Output = ()>>>>>,
// if available use your async library's Mutex to `.await` locks on `buffer` instead
buffer: Mutex<Vec<u8>>,
}
impl Test {
async fn function(self: Arc<Self>) {
for i in 0..16u8 {
let data: Vec<u8> = vec![i]; // = fs::read(&format("file-{}.txt", i)).await.unwrap();
let mut buflock = self.buffer.lock().unwrap();
buflock.extend_from_slice(&data);
}
}
pub fn new() -> Arc<Self> {
let s = Arc::new(Self {
state: Default::default(),
buffer: Default::default(),
});
{
// start by trying to aquire a lock to the Mutex of the Box
let mut lock = s.state.lock().unwrap();
// create boxed future
let b = Box::pin(s.clone().function());
// insert value into the mutex
*lock = Some(b);
} // block causes the lock to be released
s
}
}
impl Future for Test {
type Output = ();
fn poll(
self: std::pin::Pin<&mut Self>,
ctx: &mut std::task::Context<'_>,
) -> std::task::Poll<<Self as std::future::Future>::Output> {
let mut lock = self.state.lock().unwrap();
let fut: &mut Pin<Box<dyn Future<Output = ()>>> = lock.as_mut().unwrap();
Future::poll(fut.as_mut(), ctx)
}
}
I'm not sure what you want to achieve and why, but I suspect that you're trying to implement Future for Test based on some ancient tutorial or misunderstanding and just overcomplicating things.
You don't have to implement Future manually. An async function
async fn function(...) {...}
is really just syntax sugar translated behind the scenes into something like
fn function(...) -> Future<()> {...}
All you have to do is to use the result of the function the same way as any future, e.g. use await on it or call block a reactor until it's finished. E.g. based on your first version, you can simply call:
let mut test = Test{};
test.function().await;
UPDATE1
Based on your descriptions I still think you're trying to overcomplicate this minimal working snippet without the need to manually implement Future for anything:
async fn asyncio() { println!("Doing async IO"); }
struct Test {
count: u32,
}
impl Test {
async fn function(&mut self) {
asyncio().await;
self.count += 1;
}
}
#[tokio::main]
async fn main() {
let mut test = Test{count: 0};
test.function().await;
println!("Count: {}", test.count);
}

Cannot use `impl Future` to store async function in a vector

I am trying to store async functions in a vector, but it seems like impl cannot be used in the vector type definition:
use std::future::Future;
fn main() {
let mut v: Vec<fn() -> impl Future<Output = ()>> = vec![];
v.push(haha);
}
async fn haha() {
println!("haha");
}
error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
--> src/main.rs:4:28
|
4 | let mut v: Vec<fn() -> impl Future<Output = ()>> = vec![];
| ^^^^^^^^^^^^^^^^^^^^^^^^
How do I write the type inside the vector?
I found that there may be a workaround by using a type alias, so I changed the code:
use std::future::Future;
type Haha = impl Future<Output = ()>;
fn main() {
let mut v: Vec<fn() -> Haha> = vec![];
v.push(haha);
}
async fn haha() {
println!("haha");
}
This doesn't work either; this time the error occurs in the type alias:
error[E0658]: `impl Trait` in type aliases is unstable
--> src/main.rs:3:1
|
3 | type Haha = impl Future<Output = ()>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/63063
error[E0308]: mismatched types
--> src/main.rs:8:12
|
8 | v.push(haha);
| ^^^^ expected opaque type, found a different opaque type
|
= note: expected type `fn() -> Haha`
found type `fn() -> impl std::future::Future {haha}`
= note: distinct uses of `impl Trait` result in different opaque types
error: could not find defining uses
--> src/main.rs:3:1
|
3 | type Haha = impl Future<Output = ()>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
How do I fix it?
You cannot use the impl Trait this way. To be able to store different types that implement a trait into the same container you have to use dynamic dispatch, by storing something like Box<dyn Trait>.
In your particular case, you do not specify if you want to store the async functions themselves or the future generated by the async functions, the solution would be somewhat different.
To store just the futures, you write a container such as:
let mut v: Vec<Box<dyn Future<Output = ()>>> = vec![];
And then just call the function, box it and store it in the container:
v.push(Box::new(haha()));
If instead you want to store the async function itself, without calling it, you need a container with a double dyn:
let mut v2: Vec<Box<dyn Fn() -> Box<dyn Future<Output = ()>>>> = vec![];
Now, since your haha function does not implement this Fn trait you need an adaptor. A lambda function will do, but don't forget the double Box:
v2.push(Box::new(|| Box::new(haha())));
Unfortunately, with these solutions you will be able to create the vector, but not to .await for your futures. For that you need the futures to implement the Unpin marker. That guarantees to the compiler that the future will not move while it is running (if it did, the implementation would be totally unsafe). You could add the + Unpin requirement to the futures, but async fn are not Unpin so you could not fill the vector. The easiest way to fix it is to use this handy function from std:
pub fn into_pin(boxed: Box<T>) -> Pin<Box<T>>
for f in v2 {
f().into_pin().await;
}
Unfortunately, it is still unstable. Fortunately, there is a From impl that does exactly the same. So you can just write:
for f in v2 {
Pin::from(f()).await;
}
In your comment below you write this code to wait for the futures:
for f in v2 {
async { f().await }
}
Note that an async block itself will evaluate to another future, so here you are just wrapping each future into another future, but nobody is waiting for that one. Actually you'll get a warning about it:
warning: unused implementer of std::future::Future that must be used.
Remember that in order to properly wait for all the futures you will need an async runtime.
rodrigo's answer is correct, but I'd prefer to use Box::pin and bake the Pin type into the API of the collection. This makes using the Future trait object (or closure trait object producing a Future trait object) easier:
use std::{future::Future, pin::Pin};
type PinFutureObj<Output> = Pin<Box<dyn Future<Output = Output>>>;
async fn collection_of_pinned_future_trait_objects() {
let v: Vec<PinFutureObj<()>> = vec![
Box::pin(haha()),
Box::pin(hehe()),
Box::pin(haha()),
Box::pin(hehe()),
];
for f in v {
f.await
}
}
async fn collection_of_closure_trait_objects() {
let v: Vec<Box<dyn Fn() -> PinFutureObj<()>>> = vec![
Box::new(|| Box::pin(haha())),
Box::new(|| Box::pin(hehe())),
Box::new(|| Box::pin(haha())),
Box::new(|| Box::pin(hehe())),
];
for f in v {
f().await
}
}
async fn haha() {
println!("haha");
}
async fn hehe() {
println!("hehe");
}
I'd also start introducing type aliases for the longer types.
In fact, this type alias already exists in the futures crate as LocalBoxFuture and can be created via FutureExt::boxed_local. There's also BoxFuture produced by FutureExt::boxed which adds common trait bounds.
use futures::future::{FutureExt, LocalBoxFuture}; // 0.3.5
async fn collection_of_pinned_future_trait_objects() {
let v: Vec<LocalBoxFuture<'static, ()>> = vec![
haha().boxed_local(),
hehe().boxed_local(),
haha().boxed_local(),
hehe().boxed_local(),
];
for f in v {
f.await
}
}
async fn collection_of_closure_trait_objects() {
let v: Vec<Box<dyn Fn() -> LocalBoxFuture<'static, ()>>> = vec![
Box::new(|| haha().boxed_local()),
Box::new(|| hehe().boxed_local()),
Box::new(|| haha().boxed_local()),
Box::new(|| hehe().boxed_local()),
];
for f in v {
f().await
}
}
async fn haha() {
println!("haha");
}
async fn hehe() {
println!("hehe");
}
See also:
How can I put an async function into a map in Rust?
Why can impl trait not be used to return multiple / conditional types?

Convert Option<&mut T> to *mut T

I'm writing a Rust wrapper around a C library and while doing so I'm trying to take advantage of the "nullable pointer optimization" mentioned in The Book, but I can't find a good way to convert Option<&T> to *const T and Option<&mut T> to *mut T like what they're describing.
What I really want is to be able to call Some(&foo) as *const _. Unfortunately that doesn't work, so the next best thing I can think of is a trait on Option<T> that enables me to call Some(&foo).as_ptr(). The following code is a working definition and implementation for that trait:
use std::ptr;
trait AsPtr<T> {
fn as_ptr(&self) -> *const T;
}
impl<'a, T> AsPtr<T> for Option<&'a T> {
fn as_ptr(&self) -> *const T {
match *self {
Some(val) => val as *const _,
None => ptr::null(),
}
}
}
Now that I can call Some(&foo).as_ptr() to get a *const _, I want to be able to call Some(&mut foo).as_ptr() to get a *mut _. The following is the new trait I made to do this:
trait AsMutPtr<T> {
fn as_mut_ptr(&self) -> *mut T;
}
impl<'a, T> AsMutPtr<T> for Option<&'a mut T> {
fn as_mut_ptr(&self) -> *mut T {
match *self {
Some(val) => val as *mut _,
None => ptr::null_mut(),
}
}
}
The problem is, the AsMutPtr trait won't compile. When I try, I get the following error:
error[E0507]: cannot move out of borrowed content
--> src/lib.rs:22:15
|
22 | match *self {
| ^^^^^
| |
| cannot move out of borrowed content
| help: consider removing the `*`: `self`
23 | Some(val) => val as *mut _,
| --- data moved here
|
note: move occurs because `val` has type `&mut T`, which does not implement the `Copy` trait
--> src/lib.rs:23:18
|
23 | Some(val) => val as *mut _,
| ^^^
I don't see what changed between the two traits that causes it to fail — I didn't think adding mut would make that big a difference. I tried adding a ref, but that just causes a different error, and I wouldn't expect to need that anyway.
Why doesn't the AsMutPtr trait work?
Unfortunately, writing the trait impl for &mut T instead of &T does make a big difference. &mut T, as opposed to &T, is not Copy, therefore you cannot extract it out of a shared reference directly:
& &T ---> &T
& &mut T -/-> &mut T
This is fairly natural - otherwise aliasing of mutable references would be possible, which violates Rust borrowing rules.
You may ask where that outer & comes from. It actually comes from &self in as_mut_ptr() method. If you have an immutable reference to something, even if that something contains mutable references inside it, you won't be able to use them to mutate the data behind them. This also would be a violation of borrowing semantics.
Unfortunately, I see no way to do this without unsafe. You need to have &mut T "by value" in order to cast it to *mut T, but you can't get it "by value" through a shared reference. Therefore, I suggest you to use ptr::read():
use std::ptr;
impl<'a, T> AsMutPtr<T> for Option<&'a mut T> {
fn as_mut_ptr(&self) -> *mut T {
match *self {
Some(ref val) => unsafe { ptr::read(val) as *mut _ },
None => ptr::null_mut(),
}
}
}
val here is & &mut T because of ref qualifier in the pattern, therefore ptr::read(val) returns &mut T, aliasing the mutable reference. I think it is okay if it gets converted to a raw pointer immediately and does not leak out, but even though the result would be a raw pointer, it still means that you have two aliased mutable pointers. You should be very careful with what you do with them.
Alternatively, you may modify AsMutPtr::as_mut_ptr() to consume its target by value:
trait AsMutPtr<T> {
fn as_mut_ptr(self) -> *mut T;
}
impl<'a, T> AsMutPtr<T> for Option<&'a mut T> {
fn as_mut_ptr(self) -> *mut T {
match self {
Some(value) => value as *mut T,
None => ptr::null_mut()
}
}
}
However, in this case Option<&mut T> will be consumed by as_mut_ptr(). This may not be feasible if, for example, this Option<&mut T> is stored in a structure. I'm not really sure whether it is possible to somehow perform reborrowing manually with Option<&mut T> as opposed to just &mut T (it won't be triggered automatically); if it is possible, then by-value as_mut_ptr() is probably the best overall solution.
The problem is that you are reading an &mut out of an &, but &muts are not Copy so must be moved - and you can't move out of a const reference. This actually explains Vladimir Matveev insight about &&mut → &s in terms of more fundamental properties.
This is actually relatively simply solved. If you can read a *const _, you can read a *mut _. The two are the same type, bar a flag that says "be careful, this is being shared". Since dereferences are unsafe either way, there's actually no reason to stop you casting between the two.
So you can actually do
match *self {
Some(ref val) => val as *const _ as *mut _,
None => ptr::null_mut(),
}
Read the immutable reference, make it an immutable pointer and then make it a mutable pointer. Plus it's all done through safe Rust so we know we're not breaking any aliasing rules.
That said, it's probably a really bad idea to actually use that *mut pointer until the &mut reference is gone. I would be very hesitant with this, and try to rethink your wrapper to something safer.
Will this do what you expect?
trait AsMutPtr<T> {
fn as_mut_ptr(self) -> *mut T;
}
impl<T> AsMutPtr<T> for Option<*mut T> {
fn as_mut_ptr(self) -> *mut T {
match self {
Some(val) => val as *mut _,
None => ptr::null_mut(),
}
}
}
To avoid unsafe code, change the trait to accept &mut self instead of either self or &self:
trait AsMutPtr<T> {
fn as_mut_ptr(&mut self) -> *mut T;
}
impl<'a, T> AsMutPtr<T> for Option<&'a mut T> {
fn as_mut_ptr(&mut self) -> *mut T {
match self {
Some(v) => *v,
None => ptr::null_mut(),
}
}
}
You could also reduce the implementation to one line, if you felt like it:
fn as_mut_ptr(&mut self) -> *mut T {
self.as_mut().map_or_else(ptr::null_mut, |v| *v)
}
This can be used to give you multiple mutable raw pointers from the same source. This can easily lead you to causing mutable aliasing, so be careful:
fn example(mut v: Option<&mut u8>) {
let b = v.as_mut_ptr();
let a = v.as_mut_ptr();
}
I would recommend not converting the immutable reference to a mutable pointer as this is very likely to cause undefined behavior.

Resources