blob: 70d9315fff6f67aee45800db76424913bc78b053 [file] [log] [blame]
use std::io;
use crate::raw::crc32::CheckSummer;
/// Wraps any writer that counts and checksums bytes written.
pub struct CountingWriter<W> {
wtr: W,
cnt: u64,
summer: CheckSummer,
}
impl<W: io::Write> CountingWriter<W> {
/// Wrap the given writer with a counter.
pub fn new(wtr: W) -> CountingWriter<W> {
CountingWriter { wtr, cnt: 0, summer: CheckSummer::new() }
}
/// Return the total number of bytes written to the underlying writer.
///
/// The count returned is the sum of all counts resulting from a call
/// to `write`.
pub fn count(&self) -> u64 {
self.cnt
}
/// Returns the masked CRC32C checksum of the bytes written so far.
///
/// This "masked" checksum is the same one used by the Snappy frame format.
/// Masking is supposed to make the checksum robust with respect to data
/// that contains the checksum itself.
pub fn masked_checksum(&self) -> u32 {
self.summer.masked()
}
/// Unwrap the counting writer and return the inner writer.
pub fn into_inner(self) -> W {
self.wtr
}
/// Gets a reference to the underlying writer.
pub fn get_ref(&self) -> &W {
&self.wtr
}
}
impl<W: io::Write> io::Write for CountingWriter<W> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.summer.update(buf);
let n = self.wtr.write(buf)?;
self.cnt += n as u64;
Ok(n)
}
fn flush(&mut self) -> io::Result<()> {
self.wtr.flush()
}
}
#[cfg(test)]
mod tests {
use super::CountingWriter;
use std::io::Write;
#[test]
fn counts_bytes() {
let mut wtr = CountingWriter::new(vec![]);
wtr.write_all(b"foobar").unwrap();
assert_eq!(wtr.count(), 6);
}
}