I can't figure out why this code compiles:
use std::io::{Read, BufRead};
trait ReadString {
fn read_null_terminated_string(&mut self, max_size: u64) -> std::io::Result<String>;
}
impl<R> ReadString for R
where
R: BufRead,
{
fn read_null_terminated_string(&mut self, max_size: u64) -> std::io::Result<String> {
let mut buf = Vec::new();
self.take(max_size).read_until(0, &mut buf)?;
Ok(String::from_utf8_lossy(&buf).to_string())
}
}
As far as I can tell BufRead is not Copy, and BufRead::take() is:
fn take(self, limit: u64) -> Take<Self>
where
Self: Sized,
{
Take { inner: self, limit }
}
So surely the .take() should move self, which is not allowed because I only have &mut self? I even tried with my own BufRead-like trait and I did get this error:
cannot move out of `*self` which is behind a mutable reference
move occurs because `*self` has type `R`, which does not implement the `Copy` trait
So why don't I get that error with BufRead?
You're not invoking take() on type Self, you are invoking it on type &mut Self (the type of the self parameter) and it indeed consumes it. This works because Read has a blanket implementation impl<R: Read + ?Sized> Read for &mut R.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With