mirror of
https://github.com/ouch-org/ouch.git
synced 2025-06-07 12:05:46 +00:00
Moving bytes.rs implementation to utils.rs
This commit is contained in:
parent
20bcf1ecde
commit
3869c2502e
71
src/bytes.rs
71
src/bytes.rs
@ -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));
|
|
||||||
}
|
|
||||||
}
|
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
@ -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)?;
|
||||||
|
@ -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)
|
||||||
|
@ -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)?;
|
||||||
|
@ -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)?;
|
||||||
|
|
||||||
|
@ -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) {
|
||||||
|
@ -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";
|
||||||
|
82
src/utils.rs
82
src/utils.rs
@ -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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user