1

Consider the following function (using ZlibDecoder). It reads some data (just a random f64 in this case) from a reader that may or not be compressed. I use &mut dyn Read to erase the fact that compression is used (or not).

    fn read_data(reader: &mut (impl Read + Seek), is_compressed: bool) -> Result<f64> {
        let start_pos = reader.stream_position()?;
        let mut zlib_decoder;

        let mut compressed_reader: &mut dyn Read = if !is_compressed {
            reader
        } else {
            zlib_decoder = ZlibDecoder::new(reader);
            &mut zlib_decoder
        };

        let data = compressed_reader.read_f64()?;

        // Skip to next bit of data.
        reader.seek(SeekFrom::Start(start_pos + 100))?;

        Ok(data)
    }

It almost works but it gives an error like this:

error[E0382]: borrow of moved value: `reader`
    |
604 |     fn read_data(reader: &mut (impl Read + Seek), is_compressed: bool) -> Result<f64> {
    |                  ------ move occurs because `reader` has type `&mut impl Read + Seek`, which does not implement the `Copy` trait
...
621 |             zlib_decoder = ZlibDecoder::new(reader);
    |                                             ------ value moved here
...
653 |         reader.seek(SeekFrom::Start(start_pos + 100))?;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ value borrowed here after move

Ok fair enough you can't just copy a &mut impl Read - I guess that would give you two &muts to the same data which isn't allowed. But if I change the ZlibDecoder::new(reader) line to this:

            zlib_decoder = ZlibDecoder::new(&mut *reader);

Then it works! Can anyone tell me what is going on here? I kind of just guessed the solution and got lucky. I vaguely recall reading something about reborrowing and maybe it's something to do with that?

Timmmm
  • 88,195
  • 71
  • 364
  • 509

0 Answers0