Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I force a value to be moved from an inner scope to an outer instead of borrowing?

Tags:

rust

I'm newbie in Rust. How can I force a value to be moved from an inner scope to an outer instead of borrowing?

let mut r_buf = BufReader::new(file.unwrap());
let mut eof = false;

while !eof {
    let piece = r_buf.fill_buf();
    if piece.is_ok() {
        let mut piece = piece.unwrap();
        let piece_len = piece.len();

        if opt.compress {
            let deflated = deflate_bytes(piece);
            if deflated.is_none() {
                panic!(format!("Cant deflate file {}", path.to_str().unwrap_or("")));
            }

            let deflate_unwrapped = deflated.unwrap();
            let deflate_deref = deflate_unwrapped.deref();
            piece = deflate_deref;
        }
        /* bf: &mut BufStream<File>*/
        let w = bf.write(piece);

        if w.is_ok() {
            written_bytes = w.unwrap();
        }

I can't move &[u8] from deflate_deref to piece. I've tried Vec<u8> and Box<&[u8]>. I have an error "deflate_unwrapped does not live long enough"... I can't operate by [u8] type because it doesn't have an exact size in compile type, while references I can only borrow...

In this case must I use something specific or rewrite this code?

Playground link http://is.gd/u8wfm7

like image 563
Vitaliy Avatar asked Oct 14 '25 10:10

Vitaliy


1 Answers

Let’s reduce your code to a truly minimal example:

fn main() {
    let a = {
        let b = 42;
        &b
    };
}

For this is what your case is boiling down to: trying to take a reference to something and storing that reference after the original object has passed out of scope.

There are two main ways of dealing with this:

  1. Change the scope of the variable that you are taking a reference to:

    fn main() {
        let b;
        let a = {
            b = 42;
            &b
        };
    }
    

    So long as you are not dealing with crossing function boundaries (that is, returning a reference to something inside the function) or certain combinations with loop boundaries, this is typically the best solution.

  2. Don’t take a reference, but rather do what processing you wish to do with it at the time:

    fn main() {
        let a = {
            let b = 42;
            b.clone()
        };
    }
    

    In your particular case, that could be turning the &[u8] into a Vec<u8>, which can be written Vec::from(slice). Of course, in your specific example you would still need to worry about storing the vector somewhere as in the first way, or else using Cow<[u8]> for the whole thing.

There is an article that I have written which among other things considers these questions which you might find helpful: http://chrismorgan.info/blog/rust-fizzbuzz.html. It deals with String and str where you are dealing more with Vec<u8>/Bytes and [u8], but the concepts are very much the same.

like image 152
Chris Morgan Avatar answered Oct 20 '25 18:10

Chris Morgan



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!