Problem with move of referenced object, can this be solved?


#1

fn some_func(filebuf : &mut BufReader)
{
let mut iter : Peekable<Bytes<&mut BufReader>> = filebuf.bytes().peekable();
let c : u8 = iter.next().unwrap_or(Ok(0)).unwrap_or(0); // unpack option and unpack result , works
let c2 : u8 = iter.peek().unwrap_or(&Ok(0)).unwrap_or(0);
// here the &Ok(0) needs to be copied, I guess. Can i make this work, or do I need to use unwrap_or_else ?


#2

You could use a pattern: match iter.peek() { Some(&Ok(val)) => val, _ => 0 }


#3

The problem lies in the fact that the unwrap_or (same for unwrap_or_else) function gives back the Type T.
In the case of Peekable.peek the unwrap_or else does need to return a &T.
Is this correct ?

A function can only return a &T if this is somehow configured with a lifetime addition.
Is this more general assumption correct ?

Thank You.


#4

Oh, I see, iter.peek().unwrap_or(&Ok(0)) is giving you &Result<u8>, and the final unwrap_or is trying to consume that by value – which can’t move out of a reference. The problem is not what unwrap_or is returning, but that it’s really unwrap_or(self,...) trying to consume the Result when you only have &Result.

You can use as_ref() to flip that reference to Result<&u8> (roughly*), then unwrap that with a matching reference for a &u8, and just dereference that since u8 is Copy.

let c2: u8 = *iter.peek().unwrap_or(&Ok(0)).as_ref().unwrap_or(&0);

I think the match pattern is cleaner when dealing with multiple levels like this, but it’s up to you.

* I say roughly because I’m blurring the line between std::io::Result and std::result::Result. In full, as_ref() will actually give you std::result::Result<&u8, &std::io::Error>.