Moving bytes.rs implementation to utils.rs

This commit is contained in:
João M. Bezerra 2021-04-06 21:16:33 -03:00
parent 20bcf1ecde
commit 3869c2502e
11 changed files with 97 additions and 116 deletions

View File

@ -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));
}
}

View File

@ -3,20 +3,15 @@ use std::{fs, io::Write, path::PathBuf};
use colored::Colorize; use colored::Colorize;
use super::{Compressor, Entry}; use super::{Compressor, Entry};
use crate::{ use crate::{extension::CompressionFormat, file::File, utils};
bytes::Bytes,
extension::CompressionFormat,
file::File,
utils::{check_for_multiple_files, ensure_exists},
};
pub struct BzipCompressor; pub struct BzipCompressor;
impl BzipCompressor { impl BzipCompressor {
fn compress_files(files: Vec<PathBuf>, format: CompressionFormat) -> crate::Result<Vec<u8>> { fn compress_files(files: Vec<PathBuf>, format: CompressionFormat) -> crate::Result<Vec<u8>> {
check_for_multiple_files(&files, &format)?; utils::check_for_multiple_files(&files, &format)?;
let path = &files[0]; let path = &files[0];
ensure_exists(path)?; utils::ensure_exists(path)?;
let contents = { let contents = {
let bytes = fs::read(path)?; let bytes = fs::read(path)?;
Self::compress_bytes(&*bytes)? Self::compress_bytes(&*bytes)?
@ -26,7 +21,7 @@ impl BzipCompressor {
"{}: compressed {:?} into memory ({})", "{}: compressed {:?} into memory ({})",
"info".yellow(), "info".yellow(),
&path, &path,
Bytes::new(contents.len() as u64) utils::Bytes::new(contents.len() as u64)
); );
Ok(contents) Ok(contents)

View File

@ -3,12 +3,7 @@ use std::{fs, io::Write, path::PathBuf};
use colored::Colorize; use colored::Colorize;
use super::{Compressor, Entry}; use super::{Compressor, Entry};
use crate::{ use crate::{extension::CompressionFormat, file::File, utils};
bytes::Bytes,
extension::CompressionFormat,
file::File,
utils::{check_for_multiple_files, ensure_exists},
};
pub struct GzipCompressor; pub struct GzipCompressor;
@ -17,10 +12,10 @@ impl GzipCompressor {
files: Vec<PathBuf>, files: Vec<PathBuf>,
format: CompressionFormat, format: CompressionFormat,
) -> crate::Result<Vec<u8>> { ) -> crate::Result<Vec<u8>> {
check_for_multiple_files(&files, &format)?; utils::check_for_multiple_files(&files, &format)?;
let path = &files[0]; let path = &files[0];
ensure_exists(path)?; utils::ensure_exists(path)?;
let bytes = { let bytes = {
let bytes = fs::read(path)?; let bytes = fs::read(path)?;
@ -31,7 +26,7 @@ impl GzipCompressor {
"{}: compressed {:?} into memory ({})", "{}: compressed {:?} into memory ({})",
"info".yellow(), "info".yellow(),
&path, &path,
Bytes::new(bytes.len() as u64) utils::Bytes::new(bytes.len() as u64)
); );
Ok(bytes) Ok(bytes)

View File

@ -3,12 +3,7 @@ use std::{fs, io::Write, path::PathBuf};
use colored::Colorize; use colored::Colorize;
use super::{Compressor, Entry}; use super::{Compressor, Entry};
use crate::{ use crate::{extension::CompressionFormat, file::File, utils};
bytes::Bytes,
extension::CompressionFormat,
file::File,
utils::{check_for_multiple_files, ensure_exists},
};
pub struct LzmaCompressor; pub struct LzmaCompressor;
@ -17,10 +12,10 @@ impl LzmaCompressor {
files: Vec<PathBuf>, files: Vec<PathBuf>,
format: CompressionFormat, format: CompressionFormat,
) -> crate::Result<Vec<u8>> { ) -> crate::Result<Vec<u8>> {
check_for_multiple_files(&files, &format)?; utils::check_for_multiple_files(&files, &format)?;
let path = &files[0]; let path = &files[0];
ensure_exists(path)?; utils::ensure_exists(path)?;
let bytes = { let bytes = {
let bytes = fs::read(path)?; let bytes = fs::read(path)?;
@ -31,7 +26,7 @@ impl LzmaCompressor {
"{}: compressed {:?} into memory ({})", "{}: compressed {:?} into memory ({})",
"info".yellow(), "info".yellow(),
&path, &path,
Bytes::new(bytes.len() as u64) utils::Bytes::new(bytes.len() as u64)
); );
Ok(bytes) Ok(bytes)

View File

@ -8,7 +8,7 @@ use colored::Colorize;
use tar::{self, Archive}; use tar::{self, Archive};
use super::decompressor::{DecompressionResult, Decompressor}; use super::decompressor::{DecompressionResult, Decompressor};
use crate::{bytes::Bytes, dialogs::Confirmation, file::File, utils}; use crate::{dialogs::Confirmation, file::File, utils};
#[derive(Debug)] #[derive(Debug)]
pub struct TarDecompressor; pub struct TarDecompressor;
@ -48,7 +48,7 @@ impl TarDecompressor {
"{}: {:?} extracted. ({})", "{}: {:?} extracted. ({})",
"info".yellow(), "info".yellow(),
into.join(file.path()?), into.join(file.path()?),
Bytes::new(file.size()) utils::Bytes::new(file.size())
); );
let file_path = fs::canonicalize(file_path)?; let file_path = fs::canonicalize(file_path)?;

View File

@ -6,7 +6,7 @@ use std::{
use colored::Colorize; use colored::Colorize;
use super::decompressor::{DecompressionResult, Decompressor}; use super::decompressor::{DecompressionResult, Decompressor};
use crate::{bytes::Bytes, extension::CompressionFormat, file::File, utils}; use crate::{extension::CompressionFormat, file::File, utils};
struct DecompressorToMemory; struct DecompressorToMemory;
pub struct GzipDecompressor; pub struct GzipDecompressor;
@ -38,7 +38,7 @@ impl DecompressorToMemory {
"{}: {:?} extracted into memory ({}).", "{}: {:?} extracted into memory ({}).",
"info".yellow(), "info".yellow(),
path, path,
Bytes::new(bytes_read as u64) utils::Bytes::new(bytes_read as u64)
); );
Ok(buffer) Ok(buffer)

View File

@ -8,7 +8,7 @@ use colored::Colorize;
use zip::{self, read::ZipFile, ZipArchive}; use zip::{self, read::ZipFile, ZipArchive};
use super::decompressor::{DecompressionResult, Decompressor}; use super::decompressor::{DecompressionResult, Decompressor};
use crate::{bytes::Bytes, dialogs::Confirmation, file::File, utils}; use crate::{dialogs::Confirmation, file::File, utils};
#[cfg(unix)] #[cfg(unix)]
fn __unix_set_permissions(file_path: &Path, file: &ZipFile) { fn __unix_set_permissions(file_path: &Path, file: &ZipFile) {
@ -76,7 +76,7 @@ impl ZipDecompressor {
"{}: \"{}\" extracted. ({})", "{}: \"{}\" extracted. ({})",
"info".yellow(), "info".yellow(),
file_path.display(), file_path.display(),
Bytes::new(file.size()) utils::Bytes::new(file.size())
); );
let mut output_file = fs::File::create(&file_path)?; let mut output_file = fs::File::create(&file_path)?;

View File

@ -7,7 +7,6 @@ use std::{
use colored::Colorize; use colored::Colorize;
use crate::{ use crate::{
bytes::Bytes,
cli::Command, cli::Command,
compressors::{ compressors::{
BzipCompressor, Compressor, Entry, GzipCompressor, LzmaCompressor, TarCompressor, BzipCompressor, Compressor, Entry, GzipCompressor, LzmaCompressor, TarCompressor,
@ -195,7 +194,7 @@ impl Evaluator {
"{}: writing to {:?}. ({})", "{}: writing to {:?}. ({})",
"info".yellow(), "info".yellow(),
output_path, output_path,
Bytes::new(bytes.len() as u64) utils::Bytes::new(bytes.len() as u64)
); );
fs::write(output_path, bytes)?; fs::write(output_path, bytes)?;

View File

@ -7,7 +7,7 @@ use std::{
use CompressionFormat::*; use CompressionFormat::*;
use crate::utils::to_utf; use crate::utils;
/// Represents the extension of a file, but only really caring about /// Represents the extension of a file, but only really caring about
/// compression formats (and .tar). /// compression formats (and .tar).
@ -49,7 +49,7 @@ impl Extension {
_ if ext == "gz" => Ok(Gzip), _ if ext == "gz" => Ok(Gzip),
_ if ext == "bz" || ext == "bz2" => Ok(Bzip), _ if ext == "bz" || ext == "bz2" => Ok(Bzip),
_ if ext == "xz" || ext == "lz" || ext == "lzma" => Ok(Lzma), _ 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) { let (first_ext, second_ext) = match get_extension_from_filename(&file_name) {

View File

@ -3,14 +3,12 @@ pub mod cli;
pub mod evaluator; pub mod evaluator;
// Private modules // Private modules
mod bytes;
mod compressors; mod compressors;
mod decompressors; mod decompressors;
mod dialogs; mod dialogs;
mod error; mod error;
mod extension; mod extension;
mod file; mod file;
mod test;
mod utils; mod utils;
const VERSION: &str = "0.1.5"; const VERSION: &str = "0.1.5";

View File

@ -1,5 +1,5 @@
use std::{ use std::{
env, cmp, env,
ffi::OsStr, ffi::OsStr,
fs, fs,
path::{Path, PathBuf}, 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 where
P: AsRef<Path> + 'a, P: AsRef<Path> + 'a,
{ {
@ -36,7 +36,7 @@ where
Ok(()) Ok(())
} }
pub(crate) fn check_for_multiple_files( pub fn check_for_multiple_files(
files: &[PathBuf], files: &[PathBuf],
format: &CompressionFormat, format: &CompressionFormat,
) -> crate::Result<()> { ) -> crate::Result<()> {
@ -55,7 +55,7 @@ pub(crate) fn check_for_multiple_files(
Ok(()) 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() { if !path.exists() {
println!( println!(
"{}: attempting to create folder {:?}.", "{}: attempting to create folder {:?}.",
@ -72,7 +72,7 @@ pub(crate) fn create_path_if_non_existent(path: &Path) -> crate::Result<()> {
Ok(()) Ok(())
} }
pub(crate) fn get_destination_path<'a>(dest: &'a Option<File>) -> &'a Path { pub fn get_destination_path<'a>(dest: &'a Option<File>) -> &'a Path {
match dest { match dest {
Some(output_file) => { Some(output_file) => {
// Must be None according to the way command-line arg. parsing in Ouch works // 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<File>) -> &'a Path {
} }
} }
pub(crate) fn change_dir_and_return_parent(filename: &Path) -> crate::Result<PathBuf> { pub fn change_dir_and_return_parent(filename: &Path) -> crate::Result<PathBuf> {
let previous_location = env::current_dir()?; let previous_location = env::current_dir()?;
let parent = if let Some(parent) = filename.parent() { let parent = if let Some(parent) = filename.parent() {
@ -121,3 +121,73 @@ pub fn to_utf(os_str: impl AsRef<OsStr>) -> String {
let text = format!("{:?}", os_str.as_ref()); let text = format!("{:?}", os_str.as_ref());
text.trim_matches('"').to_string() 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));
}
}