Files
VirtWeb/virtweb_backend/src/utils/file_size_utils.rs

92 lines
2.3 KiB
Rust

use std::ops::Mul;
#[derive(thiserror::Error, Debug)]
enum FilesSizeUtilsError {
#[error("UnitConvertError: {0}")]
UnitConvert(String),
}
/// Holds a data size, convertible in any form
#[derive(
serde::Serialize,
serde::Deserialize,
Copy,
Clone,
Debug,
Eq,
PartialEq,
PartialOrd,
Ord,
Default,
)]
pub struct FileSize(usize);
impl FileSize {
pub const fn from_bytes(size: usize) -> Self {
Self(size)
}
pub const fn from_mb(mb: usize) -> Self {
Self(mb * 1000 * 1000)
}
pub const fn from_gb(gb: usize) -> Self {
Self(gb * 1000 * 1000 * 1000)
}
/// Convert size unit to MB
pub fn from_size_unit(unit: &str, value: usize) -> anyhow::Result<Self> {
let fact = match unit {
"bytes" | "b" => 1f64,
"KB" => 1000f64,
"MB" => 1000f64 * 1000f64,
"GB" => 1000f64 * 1000f64 * 1000f64,
"TB" => 1000f64 * 1000f64 * 1000f64 * 1000f64,
"k" | "KiB" => 1024f64,
"M" | "MiB" => 1024f64 * 1024f64,
"G" | "GiB" => 1024f64 * 1024f64 * 1024f64,
"T" | "TiB" => 1024f64 * 1024f64 * 1024f64 * 1024f64,
_ => {
return Err(
FilesSizeUtilsError::UnitConvert(format!("Unknown size unit: {unit}")).into(),
);
}
};
Ok(Self((value as f64).mul(fact).ceil() as usize))
}
/// Get file size as bytes
pub fn as_bytes(&self) -> usize {
self.0
}
/// Get file size as megabytes
pub fn as_mb(&self) -> usize {
self.0 / (1000 * 1000)
}
}
#[cfg(test)]
mod tests {
use crate::utils::file_size_utils::FileSize;
#[test]
fn convert_units_mb() {
assert_eq!(FileSize::from_size_unit("MB", 1).unwrap().as_mb(), 1);
assert_eq!(FileSize::from_size_unit("MB", 1000).unwrap().as_mb(), 1000);
assert_eq!(
FileSize::from_size_unit("GB", 1000).unwrap().as_mb(),
1000 * 1000
);
assert_eq!(FileSize::from_size_unit("GB", 1).unwrap().as_mb(), 1000);
assert_eq!(FileSize::from_size_unit("GiB", 3).unwrap().as_mb(), 3221);
assert_eq!(
FileSize::from_size_unit("KiB", 488281).unwrap().as_mb(),
499
);
}
}