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