use byteorder::{BigEndian, ReadBytesExt};
use bytes::{BufMut, BytesMut};
use std::io::{self, Cursor};
use thiserror::Error;
#[derive(Debug, Error)]
pub enum FileSummaryLnEntryError {
#[error("I/O error: {0}")]
Io(#[from] io::Error),
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct FileSummaryLnEntry {
pub file_number: u64,
pub total_count: i64,
pub total_size: i64,
pub obsolete_count: i64,
pub obsolete_size: i64,
pub obsolete_size_counted: bool,
}
impl FileSummaryLnEntry {
pub fn new(
file_number: u64,
total_count: i64,
total_size: i64,
obsolete_count: i64,
obsolete_size: i64,
obsolete_size_counted: bool,
) -> Self {
Self {
file_number,
total_count,
total_size,
obsolete_count,
obsolete_size,
obsolete_size_counted,
}
}
pub fn log_size(&self) -> usize {
8 + 8 + 8 + 8 + 8 + 1 }
pub fn write_to_log(&self, buf: &mut BytesMut) {
buf.put_u64(self.file_number);
buf.put_i64(self.total_count);
buf.put_i64(self.total_size);
buf.put_i64(self.obsolete_count);
buf.put_i64(self.obsolete_size);
buf.put_u8(if self.obsolete_size_counted { 1 } else { 0 });
}
pub fn read_from_log(buf: &[u8]) -> Result<Self, FileSummaryLnEntryError> {
let mut cursor = Cursor::new(buf);
let file_number = cursor.read_u64::<BigEndian>()?;
let total_count = cursor.read_i64::<BigEndian>()?;
let total_size = cursor.read_i64::<BigEndian>()?;
let obsolete_count = cursor.read_i64::<BigEndian>()?;
let obsolete_size = cursor.read_i64::<BigEndian>()?;
let obsolete_size_counted = cursor.read_u8()? != 0;
Ok(Self {
file_number,
total_count,
total_size,
obsolete_count,
obsolete_size,
obsolete_size_counted,
})
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_file_summary_ln_roundtrip() {
let entry = FileSummaryLnEntry::new(5, 1000, 512000, 200, 102400, true);
let mut buf = BytesMut::new();
entry.write_to_log(&mut buf);
let decoded = FileSummaryLnEntry::read_from_log(&buf).unwrap();
assert_eq!(entry, decoded);
assert_eq!(decoded.file_number, 5);
assert_eq!(decoded.total_count, 1000);
assert_eq!(decoded.total_size, 512000);
assert_eq!(decoded.obsolete_count, 200);
assert_eq!(decoded.obsolete_size, 102400);
assert!(decoded.obsolete_size_counted);
}
#[test]
fn test_file_summary_ln_not_counted() {
let entry = FileSummaryLnEntry::new(0, 0, 0, 0, 0, false);
let mut buf = BytesMut::new();
entry.write_to_log(&mut buf);
let decoded = FileSummaryLnEntry::read_from_log(&buf).unwrap();
assert_eq!(entry, decoded);
assert!(!decoded.obsolete_size_counted);
}
#[test]
fn test_log_size() {
let entry = FileSummaryLnEntry::new(1, 10, 100, 5, 50, false);
assert_eq!(entry.log_size(), 8 + 8 + 8 + 8 + 8 + 1);
let mut buf = BytesMut::new();
entry.write_to_log(&mut buf);
assert_eq!(buf.len(), entry.log_size());
}
}