Skip to content

Commit

Permalink
beginning of file size refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
solidiquis committed May 18, 2023
1 parent 4a8d0b4 commit 101e64d
Show file tree
Hide file tree
Showing 7 changed files with 217 additions and 24 deletions.
Empty file added src/disk_usage/block.rs
Empty file.
40 changes: 20 additions & 20 deletions src/disk_usage/file_size.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use std::{borrow::Cow, fs::Metadata, ops::AddAssign, path::Path};
/// Represents either logical or physical size and handles presentation.
#[derive(Clone, Debug)]
pub struct FileSize {
pub bytes: u64,
pub value: u64,
#[allow(dead_code)]
disk_usage: DiskUsage,
prefix_kind: PrefixKind,
Expand All @@ -34,21 +34,21 @@ pub enum DiskUsage {
/// How many bytes does a file contain
Logical,

/// How much actual space on disk, taking into account sparse files and compression.
/// How much actual space on disk in bytes, taking into account sparse files and compression.
#[default]
Physical,
}

impl FileSize {
/// Initializes a [`FileSize`].
pub const fn new(
bytes: u64,
value: u64,
disk_usage: DiskUsage,
human_readable: bool,
prefix_kind: PrefixKind,
) -> Self {
Self {
bytes,
value,
disk_usage,
human_readable,
prefix_kind,
Expand Down Expand Up @@ -84,22 +84,22 @@ impl FileSize {
/// Precompute the raw (unpadded) display and sets the number of columns the size (without
/// the prefix) will occupy. Also sets the [Style] to use in advance to style the size output.
pub fn precompute_unpadded_display(&mut self) {
let fbytes = self.bytes as f64;
let value = self.value as f64;

match self.prefix_kind {
PrefixKind::Si => {
let unit = SiPrefix::from(fbytes);
let unit = SiPrefix::from(value);
let base_value = unit.base_value();

if !self.human_readable {
self.unpadded_display = Some(format!("{} B", self.bytes));
self.size_columns = utils::num_integral(self.bytes);
self.unpadded_display = Some(format!("{} B", self.value));
self.size_columns = utils::num_integral(self.value);
} else if matches!(unit, SiPrefix::Base) {
self.unpadded_display = Some(format!("{} {unit}", self.bytes));
self.size_columns = utils::num_integral(self.bytes);
self.unpadded_display = Some(format!("{} {unit}", self.value));
self.size_columns = utils::num_integral(self.value);
self.uses_base_unit = Some(());
} else {
let size = fbytes / (base_value as f64);
let size = value / (base_value as f64);
self.unpadded_display = Some(format!("{size:.2} {unit}"));
self.size_columns = utils::num_integral((size * 100.0).floor() as u64) + 1;
}
Expand All @@ -110,18 +110,18 @@ impl FileSize {
}
}
PrefixKind::Bin => {
let unit = BinPrefix::from(fbytes);
let unit = BinPrefix::from(value);
let base_value = unit.base_value();

if !self.human_readable {
self.unpadded_display = Some(format!("{} B", self.bytes));
self.size_columns = utils::num_integral(self.bytes);
self.unpadded_display = Some(format!("{} B", self.value));
self.size_columns = utils::num_integral(self.value);
} else if matches!(unit, BinPrefix::Base) {
self.unpadded_display = Some(format!("{} {unit}", self.bytes));
self.size_columns = utils::num_integral(self.bytes);
self.unpadded_display = Some(format!("{} {unit}", self.value));
self.size_columns = utils::num_integral(self.value);
self.uses_base_unit = Some(());
} else {
let size = fbytes / (base_value as f64);
let size = value / (base_value as f64);
self.unpadded_display = Some(format!("{size:.2} {unit}"));
self.size_columns = utils::num_integral((size * 100.0).floor() as u64) + 1;
}
Expand All @@ -144,13 +144,13 @@ impl FileSize {
if self.uses_base_unit.is_some() {
format!(
"{:>max_size_width$} {unit:>max_size_unit_width$}",
self.bytes
self.value
)
} else {
format!("{size:>max_size_width$} {unit:>max_size_unit_width$}")
}
} else {
format!("{:<max_size_width$} B", self.bytes)
format!("{:<max_size_width$} B", self.value)
};

if let Some(style) = self.style {
Expand Down Expand Up @@ -186,6 +186,6 @@ impl FileSize {

impl AddAssign<&Self> for FileSize {
fn add_assign(&mut self, rhs: &Self) {
self.bytes += rhs.bytes;
self.value += rhs.value;
}
}
77 changes: 77 additions & 0 deletions src/disk_usage/logical.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
use super::{
ByteDisplay,
DuMetric,
units::PrefixKind,
};
use std::{
fmt::{self, Display},
fs::Metadata,
};

pub struct Size {
pub value: u64,
pub prefix_kind: PrefixKind,
pub human_readable: bool,
}

impl DuMetric for Size {}

impl Size {
pub fn new(metadata: &Metadata, prefix_kind: PrefixKind, human_readable: bool) -> Self {
let value = metadata.len();

Self {
value,
prefix_kind,
human_readable,
}
}
}

impl ByteDisplay for Size {
fn human_readable(&self) -> bool {
self.human_readable
}

fn prefix_kind(&self) -> PrefixKind {
self.prefix_kind
}

fn value(&self) -> u64 {
self.value
}
}

impl Display for Size {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
<Self as ByteDisplay>::fmt(self, f)
}
}

#[test]
fn test_logical_size() -> std::io::Result<()> {
use std::fs;

let md = fs::metadata("./tests/data/nemesis.txt")?;

let logical_size = Size::new(&md, PrefixKind::Bin, false);

let display = format!("{logical_size}");

assert_eq!(logical_size.value, 161);
assert_eq!(display, "161 B");

assert_eq!(
format!(
"{}",
Size {
value: 1_024,
prefix_kind: PrefixKind::Bin,
human_readable: true
}
),
"1.00 KiB"
);

Ok(())
}
50 changes: 49 additions & 1 deletion src/disk_usage/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,53 @@
use std::fmt;
use units::{BinPrefix, PrefixKind, SiPrefix, UnitPrefix};

/// Binary and SI prefixes
pub mod units;

/// Rules to display disk usage for individual files
/// Rules to display disk usage for individual files.
pub mod file_size;

pub mod block;

pub mod logical;

pub mod physical;

pub trait DuMetric {}

pub trait ByteDisplay {
fn prefix_kind(&self) -> PrefixKind;

fn value(&self) -> u64;

fn human_readable(&self) -> bool;

fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let value = self.value() as f64;

match self.prefix_kind() {
PrefixKind::Si => {
let unit = SiPrefix::from(value);
let base_value = unit.base_value();

if !self.human_readable() || matches!(unit, SiPrefix::Base) {
write!(f, "{} {unit}", self.value())
} else {
let size = value / (base_value as f64);
write!(f, "{size:.2} {unit}")
}
}
PrefixKind::Bin => {
let unit = BinPrefix::from(value);
let base_value = unit.base_value();

if !self.human_readable() || matches!(unit, BinPrefix::Base) {
write!(f, "{} {unit}", self.value())
} else {
let size = value / (base_value as f64);
write!(f, "{size:.2} {unit}")
}
}
}
}
}
68 changes: 68 additions & 0 deletions src/disk_usage/physical.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
use filesize::PathExt;
use super::{
units::PrefixKind,
ByteDisplay,
DuMetric,
};
use std::{
path::Path,
fmt::{self, Display},
fs::Metadata,
};

pub struct Size {
pub value: u64,
pub prefix_kind: PrefixKind,
pub human_readable: bool,
}

impl DuMetric for Size {}

impl Size {
pub fn new(path: &Path, metadata: &Metadata, prefix_kind: PrefixKind, human_readable: bool) -> Self {
let value = path.size_on_disk_fast(metadata).unwrap_or(0);

Self {
value,
prefix_kind,
human_readable,
}
}
}

impl ByteDisplay for Size {
fn human_readable(&self) -> bool {
self.human_readable
}

fn prefix_kind(&self) -> PrefixKind {
self.prefix_kind
}

fn value(&self) -> u64 {
self.value
}
}

impl Display for Size {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
<Self as ByteDisplay>::fmt(self, f)
}
}

#[test]
fn test_physical_size() -> std::io::Result<()> {
assert_eq!(
format!(
"{}",
Size {
value: 1_024,
prefix_kind: PrefixKind::Bin,
human_readable: true
}
),
"1.00 KiB"
);

Ok(())
}
2 changes: 1 addition & 1 deletion src/tree/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ impl Tree {
}
}

if dir_size.bytes > 0 {
if dir_size.value > 0 {
let dir = tree[current_node_id].get_mut();

dir_size.precompute_unpadded_display();
Expand Down
4 changes: 2 additions & 2 deletions src/tree/node/cmp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,8 @@ mod sizing {

/// Comparator that sorts [Node]s by size, largest to smallest.
pub fn comparator(a: &Node, b: &Node) -> Ordering {
let a_size = a.file_size().map_or(0, |fs| fs.bytes);
let b_size = b.file_size().map_or(0, |fs| fs.bytes);
let a_size = a.file_size().map_or(0, |fs| fs.value);
let b_size = b.file_size().map_or(0, |fs| fs.value);
b_size.cmp(&a_size)
}
/// Comparator that sorts [Node]s by size, smallest to largest.
Expand Down

0 comments on commit 101e64d

Please sign in to comment.