Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix size unit inconsistency #502

Merged
merged 3 commits into from
Sep 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 0 additions & 7 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ snap = "1.1.0"
tar = "0.4.40"
tempfile = "3.8.0"
time = { version = "0.3.28", default-features = false }
ubyte = { version = "0.10.3", default-features = false }
xz2 = "0.1.7"
zip = { version = "0.6.6", default-features = false, features = ["time"] }
zstd = { version = "0.12.4", default-features = false }
Expand Down
5 changes: 2 additions & 3 deletions src/archive/tar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,12 @@ use std::{

use fs_err as fs;
use same_file::Handle;
use ubyte::ToByteUnit;

use crate::{
error::FinalError,
info,
list::FileInArchive,
utils::{self, EscapedPathDisplay, FileVisibilityPolicy},
utils::{self, Bytes, EscapedPathDisplay, FileVisibilityPolicy},
warning,
};

Expand All @@ -41,7 +40,7 @@ pub fn unpack_archive(reader: Box<dyn Read>, output_folder: &Path, quiet: bool)
inaccessible,
"{:?} extracted. ({})",
utils::strip_cur_dir(&output_folder.join(file.path()?)),
file.size().bytes(),
Bytes::new(file.size()),
);

files_unpacked += 1;
Expand Down
5 changes: 2 additions & 3 deletions src/archive/zip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,14 @@ use filetime::{set_file_mtime, FileTime};
use fs_err as fs;
use same_file::Handle;
use time::OffsetDateTime;
use ubyte::ToByteUnit;
use zip::{self, read::ZipFile, DateTime, ZipArchive};

use crate::{
error::FinalError,
info,
list::FileInArchive,
utils::{
self, cd_into_same_dir_as, get_invalid_utf8_paths, pretty_format_list_of_paths, strip_cur_dir,
self, cd_into_same_dir_as, get_invalid_utf8_paths, pretty_format_list_of_paths, strip_cur_dir, Bytes,
EscapedPathDisplay, FileVisibilityPolicy,
},
warning,
Expand Down Expand Up @@ -74,7 +73,7 @@ where
inaccessible,
"{:?} extracted. ({})",
file_path.display(),
file.size().bytes()
Bytes::new(file.size()),
);
}

Expand Down
80 changes: 79 additions & 1 deletion src/utils/formatting.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{borrow::Cow, fmt::Display, path::Path};
use std::{borrow::Cow, cmp, fmt::Display, path::Path};

use crate::CURRENT_DIRECTORY;

Expand Down Expand Up @@ -86,3 +86,81 @@ pub fn nice_directory_display(path: &Path) -> Cow<str> {
to_utf(path)
}
}

/// Struct useful to printing bytes as kB, MB, GB, etc.
pub struct Bytes(f64);

impl Bytes {
const UNIT_PREFIXES: [&'static str; 6] = ["", "ki", "Mi", "Gi", "Ti", "Pi"];

/// Create a new Bytes.
pub fn new(bytes: u64) -> Self {
Self(bytes as f64)
}
}

impl std::fmt::Display for Bytes {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let &Self(num) = self;

debug_assert!(num >= 0.0);
if num < 1_f64 {
return write!(f, "{} B", num);
}

let delimiter = 1000_f64;
let exponent = cmp::min((num.ln() / 6.90775).floor() as i32, 4);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The constant 6.90775 here is arcane-event-horizon-magic, but it works.

If someone wants to refactor and it ends up as fast as it is, that's great, but I'm not the one who's gonna touch this relic.

I actually wanted MB instead of MiB, but I don't know how to the change the code to do so xD.


write!(
f,
"{:.2} {}B",
num / delimiter.powi(exponent),
Bytes::UNIT_PREFIXES[exponent as usize]
)
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_pretty_bytes_formatting() {
fn format_bytes(bytes: u64) -> String {
format!("{}", Bytes::new(bytes))
}
let b = 1;
let kb = b * 1000;
let mb = kb * 1000;
let gb = mb * 1000;

assert_eq!("0 B", format_bytes(0)); // This is weird
assert_eq!("1.00 B", format_bytes(b));
assert_eq!("999.00 B", format_bytes(b * 999));
assert_eq!("12.00 MiB", format_bytes(mb * 12));
assert_eq!("123.00 MiB", format_bytes(mb * 123));
assert_eq!("5.50 MiB", format_bytes(mb * 5 + kb * 500));
assert_eq!("7.54 GiB", format_bytes(gb * 7 + 540 * mb));
assert_eq!("1.20 TiB", format_bytes(gb * 1200));

// bytes
assert_eq!("234.00 B", format_bytes(234));
assert_eq!("999.00 B", format_bytes(999));
// kilobytes
assert_eq!("2.23 kiB", format_bytes(2234));
assert_eq!("62.50 kiB", format_bytes(62500));
assert_eq!("329.99 kiB", format_bytes(329990));
// megabytes
assert_eq!("2.75 MiB", format_bytes(2750000));
assert_eq!("55.00 MiB", format_bytes(55000000));
assert_eq!("987.65 MiB", format_bytes(987654321));
// gigabytes
assert_eq!("5.28 GiB", format_bytes(5280000000));
assert_eq!("95.20 GiB", format_bytes(95200000000));
assert_eq!("302.00 GiB", format_bytes(302000000000));
assert_eq!("302.99 GiB", format_bytes(302990000000));
// Weird aproximation cases:
assert_eq!("999.90 GiB", format_bytes(999900000000));
assert_eq!("1.00 TiB", format_bytes(999990000000));
}
}
4 changes: 3 additions & 1 deletion src/utils/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ mod fs;
mod question;

pub use file_visibility::FileVisibilityPolicy;
pub use formatting::{nice_directory_display, pretty_format_list_of_paths, strip_cur_dir, to_utf, EscapedPathDisplay};
pub use formatting::{
nice_directory_display, pretty_format_list_of_paths, strip_cur_dir, to_utf, Bytes, EscapedPathDisplay,
};
pub use fs::{
cd_into_same_dir_as, clear_path, create_dir_if_non_existent, is_symlink, remove_file_or_dir, try_infer_extension,
};
Expand Down