diff --git a/src/bytes.rs b/src/bytes.rs deleted file mode 100644 index 25ec575..0000000 --- a/src/bytes.rs +++ /dev/null @@ -1,71 +0,0 @@ -use std::cmp; - -const UNIT_PREFIXES: [&str; 6] = ["", "k", "M", "G", "T", "P"]; - -pub struct Bytes { - bytes: f64, -} - -impl Bytes { - pub fn new(bytes: u64) -> Self { - Self { - bytes: bytes as f64, - } - } -} - -impl std::fmt::Display for Bytes { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let num = self.bytes; - 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); - - write!(f, "{:.2} ", num / delimiter.powi(exponent))?; - write!(f, "{}B", UNIT_PREFIXES[exponent as usize]) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_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 MB", format_bytes(mb * 12)); - assert_eq!("123.00 MB", format_bytes(mb * 123)); - assert_eq!("5.50 MB", format_bytes(mb * 5 + kb * 500)); - assert_eq!("7.54 GB", format_bytes(gb * 7 + 540 * mb)); - assert_eq!("1.20 TB", 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 kB", format_bytes(2234)); - assert_eq!("62.50 kB", format_bytes(62500)); - assert_eq!("329.99 kB", format_bytes(329990)); - // megabytes - assert_eq!("2.75 MB", format_bytes(2750000)); - assert_eq!("55.00 MB", format_bytes(55000000)); - assert_eq!("987.65 MB", format_bytes(987654321)); - // gigabytes - assert_eq!("5.28 GB", format_bytes(5280000000)); - assert_eq!("95.20 GB", format_bytes(95200000000)); - assert_eq!("302.00 GB", format_bytes(302000000000)); - } -} diff --git a/src/compressors/bzip.rs b/src/compressors/bzip.rs index 43fea59..a08c7c9 100644 --- a/src/compressors/bzip.rs +++ b/src/compressors/bzip.rs @@ -3,20 +3,15 @@ use std::{fs, io::Write, path::PathBuf}; use colored::Colorize; use super::{Compressor, Entry}; -use crate::{ - bytes::Bytes, - extension::CompressionFormat, - file::File, - utils::{check_for_multiple_files, ensure_exists}, -}; +use crate::{extension::CompressionFormat, file::File, utils}; pub struct BzipCompressor; impl BzipCompressor { fn compress_files(files: Vec, format: CompressionFormat) -> crate::Result> { - check_for_multiple_files(&files, &format)?; + utils::check_for_multiple_files(&files, &format)?; let path = &files[0]; - ensure_exists(path)?; + utils::ensure_exists(path)?; let contents = { let bytes = fs::read(path)?; Self::compress_bytes(&*bytes)? @@ -26,7 +21,7 @@ impl BzipCompressor { "{}: compressed {:?} into memory ({})", "info".yellow(), &path, - Bytes::new(contents.len() as u64) + utils::Bytes::new(contents.len() as u64) ); Ok(contents) diff --git a/src/compressors/gzip.rs b/src/compressors/gzip.rs index 6824d2c..9399469 100644 --- a/src/compressors/gzip.rs +++ b/src/compressors/gzip.rs @@ -3,12 +3,7 @@ use std::{fs, io::Write, path::PathBuf}; use colored::Colorize; use super::{Compressor, Entry}; -use crate::{ - bytes::Bytes, - extension::CompressionFormat, - file::File, - utils::{check_for_multiple_files, ensure_exists}, -}; +use crate::{extension::CompressionFormat, file::File, utils}; pub struct GzipCompressor; @@ -17,10 +12,10 @@ impl GzipCompressor { files: Vec, format: CompressionFormat, ) -> crate::Result> { - check_for_multiple_files(&files, &format)?; + utils::check_for_multiple_files(&files, &format)?; let path = &files[0]; - ensure_exists(path)?; + utils::ensure_exists(path)?; let bytes = { let bytes = fs::read(path)?; @@ -31,7 +26,7 @@ impl GzipCompressor { "{}: compressed {:?} into memory ({})", "info".yellow(), &path, - Bytes::new(bytes.len() as u64) + utils::Bytes::new(bytes.len() as u64) ); Ok(bytes) diff --git a/src/compressors/lzma.rs b/src/compressors/lzma.rs index 5517730..d18fc0d 100644 --- a/src/compressors/lzma.rs +++ b/src/compressors/lzma.rs @@ -3,12 +3,7 @@ use std::{fs, io::Write, path::PathBuf}; use colored::Colorize; use super::{Compressor, Entry}; -use crate::{ - bytes::Bytes, - extension::CompressionFormat, - file::File, - utils::{check_for_multiple_files, ensure_exists}, -}; +use crate::{extension::CompressionFormat, file::File, utils}; pub struct LzmaCompressor; @@ -17,10 +12,10 @@ impl LzmaCompressor { files: Vec, format: CompressionFormat, ) -> crate::Result> { - check_for_multiple_files(&files, &format)?; + utils::check_for_multiple_files(&files, &format)?; let path = &files[0]; - ensure_exists(path)?; + utils::ensure_exists(path)?; let bytes = { let bytes = fs::read(path)?; @@ -31,7 +26,7 @@ impl LzmaCompressor { "{}: compressed {:?} into memory ({})", "info".yellow(), &path, - Bytes::new(bytes.len() as u64) + utils::Bytes::new(bytes.len() as u64) ); Ok(bytes) diff --git a/src/decompressors/tar.rs b/src/decompressors/tar.rs index d3374d3..7981750 100644 --- a/src/decompressors/tar.rs +++ b/src/decompressors/tar.rs @@ -8,7 +8,7 @@ use colored::Colorize; use tar::{self, Archive}; use super::decompressor::{DecompressionResult, Decompressor}; -use crate::{bytes::Bytes, dialogs::Confirmation, file::File, utils}; +use crate::{dialogs::Confirmation, file::File, utils}; #[derive(Debug)] pub struct TarDecompressor; @@ -48,7 +48,7 @@ impl TarDecompressor { "{}: {:?} extracted. ({})", "info".yellow(), into.join(file.path()?), - Bytes::new(file.size()) + utils::Bytes::new(file.size()) ); let file_path = fs::canonicalize(file_path)?; diff --git a/src/decompressors/to_memory.rs b/src/decompressors/to_memory.rs index 3a3f47f..a76e060 100644 --- a/src/decompressors/to_memory.rs +++ b/src/decompressors/to_memory.rs @@ -6,7 +6,7 @@ use std::{ use colored::Colorize; use super::decompressor::{DecompressionResult, Decompressor}; -use crate::{bytes::Bytes, extension::CompressionFormat, file::File, utils}; +use crate::{extension::CompressionFormat, file::File, utils}; struct DecompressorToMemory; pub struct GzipDecompressor; @@ -38,7 +38,7 @@ impl DecompressorToMemory { "{}: {:?} extracted into memory ({}).", "info".yellow(), path, - Bytes::new(bytes_read as u64) + utils::Bytes::new(bytes_read as u64) ); Ok(buffer) diff --git a/src/decompressors/zip.rs b/src/decompressors/zip.rs index e3d2cb9..ac2120c 100644 --- a/src/decompressors/zip.rs +++ b/src/decompressors/zip.rs @@ -8,7 +8,7 @@ use colored::Colorize; use zip::{self, read::ZipFile, ZipArchive}; use super::decompressor::{DecompressionResult, Decompressor}; -use crate::{bytes::Bytes, dialogs::Confirmation, file::File, utils}; +use crate::{dialogs::Confirmation, file::File, utils}; #[cfg(unix)] fn __unix_set_permissions(file_path: &Path, file: &ZipFile) { @@ -76,7 +76,7 @@ impl ZipDecompressor { "{}: \"{}\" extracted. ({})", "info".yellow(), file_path.display(), - Bytes::new(file.size()) + utils::Bytes::new(file.size()) ); let mut output_file = fs::File::create(&file_path)?; diff --git a/src/evaluator.rs b/src/evaluator.rs index beb04a1..1fbf017 100644 --- a/src/evaluator.rs +++ b/src/evaluator.rs @@ -7,7 +7,6 @@ use std::{ use colored::Colorize; use crate::{ - bytes::Bytes, cli::Command, compressors::{ BzipCompressor, Compressor, Entry, GzipCompressor, LzmaCompressor, TarCompressor, @@ -195,7 +194,7 @@ impl Evaluator { "{}: writing to {:?}. ({})", "info".yellow(), output_path, - Bytes::new(bytes.len() as u64) + utils::Bytes::new(bytes.len() as u64) ); fs::write(output_path, bytes)?; diff --git a/src/extension.rs b/src/extension.rs index 6ca7e4d..06de63d 100644 --- a/src/extension.rs +++ b/src/extension.rs @@ -7,7 +7,7 @@ use std::{ use CompressionFormat::*; -use crate::utils::to_utf; +use crate::utils; /// Represents the extension of a file, but only really caring about /// compression formats (and .tar). @@ -49,7 +49,7 @@ impl Extension { _ if ext == "gz" => Ok(Gzip), _ if ext == "bz" || ext == "bz2" => Ok(Bzip), _ if ext == "xz" || ext == "lz" || ext == "lzma" => Ok(Lzma), - other => Err(crate::Error::UnknownExtensionError(to_utf(other))), + other => Err(crate::Error::UnknownExtensionError(utils::to_utf(other))), }; let (first_ext, second_ext) = match get_extension_from_filename(&file_name) { diff --git a/src/lib.rs b/src/lib.rs index 946f03c..9c51d9a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,14 +3,12 @@ pub mod cli; pub mod evaluator; // Private modules -mod bytes; mod compressors; mod decompressors; mod dialogs; mod error; mod extension; mod file; -mod test; mod utils; const VERSION: &str = "0.1.5"; diff --git a/src/utils.rs b/src/utils.rs index 1953ccf..64df0e0 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,5 +1,5 @@ use std::{ - env, + cmp, env, ffi::OsStr, fs, path::{Path, PathBuf}, @@ -25,7 +25,7 @@ macro_rules! debug { }; } -pub(crate) fn ensure_exists<'a, P>(path: P) -> crate::Result<()> +pub fn ensure_exists<'a, P>(path: P) -> crate::Result<()> where P: AsRef + 'a, { @@ -36,7 +36,7 @@ where Ok(()) } -pub(crate) fn check_for_multiple_files( +pub fn check_for_multiple_files( files: &[PathBuf], format: &CompressionFormat, ) -> crate::Result<()> { @@ -55,7 +55,7 @@ pub(crate) fn check_for_multiple_files( Ok(()) } -pub(crate) fn create_path_if_non_existent(path: &Path) -> crate::Result<()> { +pub fn create_path_if_non_existent(path: &Path) -> crate::Result<()> { if !path.exists() { println!( "{}: attempting to create folder {:?}.", @@ -72,7 +72,7 @@ pub(crate) fn create_path_if_non_existent(path: &Path) -> crate::Result<()> { Ok(()) } -pub(crate) fn get_destination_path<'a>(dest: &'a Option) -> &'a Path { +pub fn get_destination_path<'a>(dest: &'a Option) -> &'a Path { match dest { Some(output_file) => { // Must be None according to the way command-line arg. parsing in Ouch works @@ -83,7 +83,7 @@ pub(crate) fn get_destination_path<'a>(dest: &'a Option) -> &'a Path { } } -pub(crate) fn change_dir_and_return_parent(filename: &Path) -> crate::Result { +pub fn change_dir_and_return_parent(filename: &Path) -> crate::Result { let previous_location = env::current_dir()?; let parent = if let Some(parent) = filename.parent() { @@ -121,3 +121,73 @@ pub fn to_utf(os_str: impl AsRef) -> String { let text = format!("{:?}", os_str.as_ref()); text.trim_matches('"').to_string() } + +pub struct Bytes { + bytes: f64, +} + +impl Bytes { + const UNIT_PREFIXES: [&'static str; 6] = ["", "k", "M", "G", "T", "P"]; + + pub fn new(bytes: u64) -> Self { + Self { + bytes: bytes as f64, + } + } +} + +impl std::fmt::Display for Bytes { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let num = self.bytes; + 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); + + write!(f, "{:.2} ", num / delimiter.powi(exponent))?; + write!(f, "{}B", 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 MB", format_bytes(mb * 12)); + assert_eq!("123.00 MB", format_bytes(mb * 123)); + assert_eq!("5.50 MB", format_bytes(mb * 5 + kb * 500)); + assert_eq!("7.54 GB", format_bytes(gb * 7 + 540 * mb)); + assert_eq!("1.20 TB", 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 kB", format_bytes(2234)); + assert_eq!("62.50 kB", format_bytes(62500)); + assert_eq!("329.99 kB", format_bytes(329990)); + // megabytes + assert_eq!("2.75 MB", format_bytes(2750000)); + assert_eq!("55.00 MB", format_bytes(55000000)); + assert_eq!("987.65 MB", format_bytes(987654321)); + // gigabytes + assert_eq!("5.28 GB", format_bytes(5280000000)); + assert_eq!("95.20 GB", format_bytes(95200000000)); + assert_eq!("302.00 GB", format_bytes(302000000000)); + } +}