ebarnard / rust-plist

A rusty plist parser.
MIT License
71 stars 42 forks source link

`to_writer_xml` consumes the writer #104

Closed amsam0 closed 1 year ago

amsam0 commented 1 year ago

Hi, it seems like to_writer_xml consumes the writer, making it impossible to use the output.

For example, here is a Value to bytes utility method:

fn to_bytes(value: Value) -> Vec<u8> {
    let bytes = vec![];
    self.to_writer_xml(bytes).unwrap();
    bytes // compile error since bytes has been consumed and wasn't returned by the function
}

I couldn't find anything in the tests on how to use this method.

amsam0 commented 1 year ago

I was able to get around it with this:

/// A wrapper for a writer that uses a reference to the writer instead of consuming the writer. Useful for methods that consume the writer, even when you want to use the writer after using the method on the writer
struct WriteWrapper<'a, W: Write>(&'a mut W);

impl<W: Write> Write for WriteWrapper<'_, W> {
    fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
        self.0.write(buf)
    }

    fn flush(&mut self) -> std::io::Result<()> {
        self.0.flush()
    }
}
ebarnard commented 1 year ago

You can pass &mut T: Write to any function accepting T: Write, so your first example is just:

fn to_bytes(value: Value) -> Vec<u8> {
    let mut bytes = vec![];
    value.to_writer_xml(&mut bytes).unwrap();
    bytes
}

Because of this implementation: https://doc.rust-lang.org/stable/std/io/trait.Write.html#impl-Write-for-%26mut%20W

amsam0 commented 1 year ago

I see, thank you!