use crate::file_summary::FileSummary;
#[derive(Debug, Clone)]
pub struct TrackedFileSummary {
file_number: u32,
summary: FileSummary,
obsolete_offsets: Vec<u32>,
modified: bool,
track_detail: bool,
}
impl TrackedFileSummary {
pub fn new(file_number: u32, track_detail: bool) -> Self {
Self {
file_number,
summary: FileSummary::new(),
obsolete_offsets: Vec::new(),
modified: false,
track_detail,
}
}
pub fn get_file_number(&self) -> u32 {
self.file_number
}
pub fn get_summary(&self) -> &FileSummary {
&self.summary
}
pub fn get_summary_mut(&mut self) -> &mut FileSummary {
self.modified = true;
&mut self.summary
}
pub fn is_modified(&self) -> bool {
self.modified
}
pub fn clear_modified(&mut self) {
self.modified = false;
}
pub fn add_obsolete_offset(&mut self, offset: u32) {
if !self.track_detail {
return;
}
self.obsolete_offsets.push(offset);
self.modified = true;
}
pub fn get_obsolete_offsets(&self) -> &[u32] {
&self.obsolete_offsets
}
pub fn is_track_detail(&self) -> bool {
self.track_detail
}
pub fn reset(&mut self) {
self.summary.reset();
self.obsolete_offsets.clear();
self.modified = false;
}
pub fn add_tracked_summary(&mut self, other: &TrackedFileSummary) {
self.summary.add(&other.summary);
if self.track_detail && other.track_detail {
self.obsolete_offsets.extend_from_slice(&other.obsolete_offsets);
}
self.modified = true;
}
pub fn obsolete_offset_count(&self) -> usize {
self.obsolete_offsets.len()
}
pub fn memory_size(&self) -> usize {
std::mem::size_of::<Self>()
+ (self.obsolete_offsets.capacity() * std::mem::size_of::<u32>())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_new() {
let tracked = TrackedFileSummary::new(42, true);
assert_eq!(tracked.get_file_number(), 42);
assert!(tracked.get_summary().is_empty());
assert!(tracked.get_obsolete_offsets().is_empty());
assert!(!tracked.is_modified());
assert!(tracked.is_track_detail());
}
#[test]
fn test_new_no_detail() {
let tracked = TrackedFileSummary::new(42, false);
assert!(!tracked.is_track_detail());
}
#[test]
fn test_add_obsolete_offset() {
let mut tracked = TrackedFileSummary::new(42, true);
tracked.add_obsolete_offset(100);
tracked.add_obsolete_offset(200);
tracked.add_obsolete_offset(300);
assert_eq!(tracked.obsolete_offset_count(), 3);
assert_eq!(tracked.get_obsolete_offsets(), &[100, 200, 300]);
assert!(tracked.is_modified());
}
#[test]
fn test_add_obsolete_offset_no_detail() {
let mut tracked = TrackedFileSummary::new(42, false);
tracked.add_obsolete_offset(100);
tracked.add_obsolete_offset(200);
assert_eq!(tracked.obsolete_offset_count(), 0);
}
#[test]
fn test_modify_summary() {
let mut tracked = TrackedFileSummary::new(42, true);
assert!(!tracked.is_modified());
{
let summary = tracked.get_summary_mut();
summary.total_count = 10;
summary.total_size = 1000;
}
assert!(tracked.is_modified());
assert_eq!(tracked.get_summary().total_count, 10);
}
#[test]
fn test_clear_modified() {
let mut tracked = TrackedFileSummary::new(42, true);
tracked.add_obsolete_offset(100);
assert!(tracked.is_modified());
tracked.clear_modified();
assert!(!tracked.is_modified());
}
#[test]
fn test_reset() {
let mut tracked = TrackedFileSummary::new(42, true);
tracked.get_summary_mut().total_count = 10;
tracked.add_obsolete_offset(100);
tracked.add_obsolete_offset(200);
tracked.reset();
assert!(tracked.get_summary().is_empty());
assert_eq!(tracked.obsolete_offset_count(), 0);
assert!(!tracked.is_modified());
}
#[test]
fn test_add_tracked_summary() {
let mut tracked1 = TrackedFileSummary::new(42, true);
tracked1.get_summary_mut().total_count = 10;
tracked1.get_summary_mut().total_size = 1000;
tracked1.add_obsolete_offset(100);
let mut tracked2 = TrackedFileSummary::new(43, true);
tracked2.get_summary_mut().total_count = 5;
tracked2.get_summary_mut().total_size = 500;
tracked2.add_obsolete_offset(200);
tracked1.add_tracked_summary(&tracked2);
assert_eq!(tracked1.get_summary().total_count, 15);
assert_eq!(tracked1.get_summary().total_size, 1500);
assert_eq!(tracked1.obsolete_offset_count(), 2);
assert_eq!(tracked1.get_obsolete_offsets(), &[100, 200]);
assert!(tracked1.is_modified());
}
#[test]
fn test_add_tracked_summary_mixed_detail() {
let mut tracked1 = TrackedFileSummary::new(42, true);
tracked1.add_obsolete_offset(100);
let mut tracked2 = TrackedFileSummary::new(43, false);
tracked2.get_summary_mut().total_count = 5;
tracked1.add_tracked_summary(&tracked2);
assert_eq!(tracked1.obsolete_offset_count(), 1);
}
#[test]
fn test_memory_size() {
let mut tracked = TrackedFileSummary::new(42, true);
let base_size = tracked.memory_size();
tracked.add_obsolete_offset(100);
tracked.add_obsolete_offset(200);
tracked.add_obsolete_offset(300);
assert!(tracked.memory_size() >= base_size);
}
#[test]
fn test_clone() {
let mut tracked1 = TrackedFileSummary::new(42, true);
tracked1.get_summary_mut().total_count = 10;
tracked1.add_obsolete_offset(100);
tracked1.add_obsolete_offset(200);
let tracked2 = tracked1.clone();
assert_eq!(tracked2.get_file_number(), 42);
assert_eq!(tracked2.get_summary().total_count, 10);
assert_eq!(tracked2.obsolete_offset_count(), 2);
assert_eq!(tracked2.get_obsolete_offsets(), &[100, 200]);
}
#[test]
fn test_get_summary_immutable() {
let mut tracked = TrackedFileSummary::new(42, true);
tracked.get_summary_mut().total_count = 10;
tracked.clear_modified();
let _summary = tracked.get_summary();
assert!(!tracked.is_modified());
}
}