use bytesize::ByteSize;
use cli_table::format::{Border, Justify, Separator};
use cli_table::{print_stdout, Cell, Row, RowStruct, Table};
use format_num::NumberFormat;
#[derive(Debug, Default)]
pub struct Stats {
unique: u64,
total: u64,
size: u64,
}
impl Stats {
pub fn new() -> Stats {
Stats::default()
}
#[inline]
pub fn add_unique(&mut self) {
self.total += 1;
self.unique += 1;
}
#[inline]
pub fn add_duplicate(&mut self) {
self.total += 1;
}
#[inline]
pub fn add_size(&mut self, size: usize) {
self.size += size as u64
}
pub fn duplicates(&self) -> u64 {
self.total - self.unique
}
pub fn rate(&self) -> f32 {
((self.unique as f64 / self.total as f64) * 100.0) as f32
}
pub fn size(&self) -> u64 {
self.size
}
pub fn total(&self) -> u64 {
self.total
}
pub fn uniques(&self) -> u64 {
self.unique
}
pub fn print(&self) {
let num = NumberFormat::new();
let table = vec![
create_row(
&num,
"File Size:",
self.size() as f64,
",.0",
&format!(
"\x08(~{})",
ByteSize::b(self.size()).display().si().to_string()
),
),
create_row(&num, "Total Count:", self.total() as f64, ",.0", ""),
create_row(&num, "Unique Count:", self.uniques() as f64, ",.0", ""),
create_row(&num, "Dup Offset:", self.duplicates() as f64, ",.0", ""),
create_row(
&num,
"Dup Rate:",
((100.0 - self.rate()) / 100.0) as f64,
",.2%",
"",
),
]
.table()
.border(Border::builder().build())
.separator(Separator::builder().build());
print_stdout(table).expect("unable to print stats table")
}
}
fn create_row(num: &NumberFormat, label: &str, value: f64, fmt: &str, ext: &str) -> RowStruct {
vec![
format!("\x08{}", label).cell(),
num.format(fmt, value).cell().justify(Justify::Right),
ext.cell(),
]
.row()
}
#[cfg(test)]
mod tests {
use super::Stats;
#[test]
fn default_creation() {
let stats = Stats::new();
assert_eq!(stats.total(), 0);
assert_eq!(stats.uniques(), 0);
assert_eq!(stats.duplicates(), 0);
}
#[test]
fn addition_of_uniques() {
let mut stats = Stats::new();
stats.add_unique();
stats.add_unique();
stats.add_unique();
assert_eq!(stats.total(), 3);
assert_eq!(stats.uniques(), 3);
assert_eq!(stats.duplicates(), 0);
}
#[test]
fn addition_of_duplicates() {
let mut stats = Stats::new();
stats.add_duplicate();
stats.add_duplicate();
stats.add_duplicate();
assert_eq!(stats.total(), 3);
assert_eq!(stats.uniques(), 0);
assert_eq!(stats.duplicates(), 3);
}
#[test]
fn generate_of_rates() {
let mut stats = Stats::new();
stats.add_duplicate();
stats.add_duplicate();
stats.add_duplicate();
stats.add_unique();
stats.add_unique();
stats.add_unique();
assert_eq!(stats.total(), 6);
assert_eq!(stats.uniques(), 3);
assert_eq!(stats.duplicates(), 3);
assert_eq!(stats.rate() as u16, 50);
}
}