This compiles and passes the test:
use std::io::Write;
/*
* This transforms a writer into a writer where every write is prefixed
* with a timestamp and terminated with a newline.
*/
struct Timestamper<T: Write> {
writer: T,
}
impl<T: Write> Timestamper<T> {
pub fn new(writer: T) -> Timestamper<T> {
Timestamper { writer }
}
pub fn drop(self) -> T {
self.writer
}
}
impl<T: Write> Write for Timestamper<T> {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
self.writer.write(b"timestamp ")?;
let expected_size = self.writer.write(buf)?;
self.writer.write(b"\n")?;
std::io::Result::Ok(expected_size)
}
fn flush(&mut self) -> std::io::Result<()> {
self.writer.flush()
}
}
#[cfg(test)]
mod tests {
use std::io::Write;
use super::Timestamper;
#[test]
fn test_timestamper() {
let buf = Vec::new(); // buffer to write into
let mut timestamper = Timestamper::new(buf);
let hello_len = timestamper.write(b"hello").unwrap();
let world_len = timestamper.write(b"world").unwrap();
assert_eq!(hello_len, 5);
assert_eq!(world_len, 5);
let buf2 = timestamper.drop();
assert_eq!(buf2.as_slice(), b"timestamp hello\ntimestamp world\n");
}
}
Is making a drop() method, which returns the writer object, idiomatic in Rust?
Is drop() the correct name for a final unwrapping function?
>Solution :
This is a common approach in Rust, but you shouldn’t call the method drop(). The Drop::drop() mehtod has different semantics. The common name for a method returning the wrapped value is into_inner().
Depending on your use case, you could also pass a mutable reference to a writer into the wrapper. Mutable references to an object implementing Write also implement Write, so this will work without any further code. The advantage of using a borrow is that you don’t need to do anything to get the original writer back. Once the borrow ends, you can immediately use the original value again. The downside is that you can’t unwrap the wrapped writer in a different context than where you created the struct.