BufReader wants to move, when I'm passing by ref

Okey, this code is a bit messy, but i am trying to read Master file tables from multiple partitions. So i wrapped the BufReader in an OffsetBufReader to be able set a custom offset when passing the reader to different parsers.

use std::io:: {
    Seek,
    SeekFrom,
    Read,
    Result,
};

#[derive(Debug, Clone, Copy)]
pub struct OffsetBufReader<R> {
    reader: R,
    offset: u64,
}

impl<R: Seek + Read> OffsetBufReader<R> {

    pub fn from_reader(mut reader: R, offset: u64) -> Result<Self>
    where R: Seek
    {
        let start = reader.seek(SeekFrom::Start(offset));

        let buffer = match start {
            Ok(_) => OffsetBufReader{ reader, offset },
            Err(e) => return Err(e)
        };

        Ok(buffer)
    }

    pub fn set_new_offset(&mut self, offset: u64) {
        self.reader.seek(SeekFrom::Start(offset))
        .expect("Could not seek to offset");
        self.offset = offset;
    }
}

impl<R: Seek> Seek for OffsetBufReader<R> {
    fn seek(&mut self, from: SeekFrom) -> Result<u64> {
        let from = match from {
            SeekFrom::Start(offset) => SeekFrom::Start(offset + self.offset as u64),
            _ => from,
        };
        self.reader.seek(from)
    }
}

impl<R: Read> Read for OffsetBufReader<R> {
    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
        self.reader.read(buf)
    }
}

I create this OffsetBufReader and pass the reader by_ref. Then i

    // Here i create it
    let mut offset_buffer = OffsetBufReader::from_reader(reader.by_ref(), data_starting_address)
        .expect("Could not create buffered reader with an offset");

    // And here i want to pass it into a function
    parse_gpt(offset_buffer.by_ref(), logical_sector_size, data_starting_address)?;

The borrow checker insists on moving it into the function, because it does not implement the copy trait, but i don't want to move it. I want to pass it by ref.

fn parse_gpt<R: Read + Seek>(reader: &mut OffsetBufReader<R>, logical_sector_size: u32, data_starting_address: u64) -> Result<(), Box<dyn Error>>{
    
    // Read the GPT
    let gpt = gptman::GPT::read_from(reader, logical_sector_size as u64)?;

    for (_, p) in gpt.iter() {
        if p.is_used() {

            // Some omitted logic

            // Setting a new offset
            reader.set_new_offset(mft_absolut_address);
            let mut mft = MftParser::from_read_seek(reader, None).unwrap();
            
            ...
        }
    }
    Ok(())
}

The error is telling me, that it first moves it into the function. Then it is borrowed after the move. And then it wants to move it again during the next iteration.

error[E0382]: borrow of moved value: `reader`
   --> src/main.rs:128:13
    |
115 | fn parse_gpt<R: Read + Seek>(reader: &mut OffsetBufReader<R>, logical_sector_size: u32, vhdx_data_starting_address: u64, filename: &str) ...
    |                              ------ move occurs because `reader` has type `&mut utils::offset_buf_reader::OffsetBufReader<R>`, which does not implement the `Copy` trait
...
128 |             reader.set_new_offset(mft_absolut_address);
    |             ^^^^^^ value borrowed here after move
...
132 |             let mut mft = MftParser::from_read_seek(reader, None).unwrap();
    |                                                     ------ value moved here, in previous iteration of loop

So here are my questions becuase i dont really understand the following:

  • Why is it moving it in the first place when im trying to pass it by_ref
  • Why does it want to move it en each iteration?
  • How should one solve this?

I have only been coding rust for about 3 weeks so im not that good at it yet.

Can you pass &mut reader to MftParser::from_read_seek?

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.