When writing to a binary file-format, its useful to be able to check how many bytes have been written (for alignment for example), or just to ensure nested functions wrote the correct amount of data.
Is there a way to inspect std::io::Write to know how much has been written? If not, what would be a good approach to wrap the writer so it could track how many bytes have been written?
Write has two required methods: write and flush. Since write already returns the number of bytes written, you just track that:
use std::io::{self, Write};
struct ByteCounter<W> {
inner: W,
count: usize,
}
impl<W> ByteCounter<W>
where W: Write
{
fn new(inner: W) -> Self {
ByteCounter {
inner: inner,
count: 0,
}
}
fn into_inner(self) -> W {
self.inner
}
fn bytes_written(&self) -> usize {
self.count
}
}
impl<W> Write for ByteCounter<W>
where W: Write
{
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
let res = self.inner.write(buf);
if let Ok(size) = res {
self.count += size
}
res
}
fn flush(&mut self) -> io::Result<()> {
self.inner.flush()
}
}
fn main() {
let out = std::io::stdout();
let mut out = ByteCounter::new(out);
writeln!(&mut out, "Hello, world! {}", 42).unwrap();
println!("Wrote {} bytes", out.bytes_written());
}
It's important to not delegate write_all or write_fmt because these do not return the count of bytes. Delegating them would allow bytes to be written and not tracked.
If the type you write to implements std::io::Seek, you can use seek to get the current position:
pos = f.seek(SeekFrom::Current(0))?;
Seek is implemented by std::fs::File (and std::io::BufWriter if the wrapped type implements Seek too).
So the function signature:
use ::std::io::{Write, Seek, SeekFrom, Error};
fn my_write<W: Write>(f: &mut W) -> Result<(), Error> { ... }
Needs to have the Seek trait added:
fn my_write<W: Write + Seek>(f: &mut W) -> Result<(), Error> { ... }
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