summaryrefslogtreecommitdiffstats
path: root/vendor/bytesize/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/bytesize/src/lib.rs')
-rw-r--r--vendor/bytesize/src/lib.rs377
1 files changed, 377 insertions, 0 deletions
diff --git a/vendor/bytesize/src/lib.rs b/vendor/bytesize/src/lib.rs
new file mode 100644
index 000000000..e2d63c9c5
--- /dev/null
+++ b/vendor/bytesize/src/lib.rs
@@ -0,0 +1,377 @@
+//! ByteSize is an utility that easily makes bytes size representation
+//! and helps its arithmetic operations.
+//!
+//! ## Example
+//!
+//! ```ignore
+//! extern crate bytesize;
+//!
+//! use bytesize::ByteSize;
+//!
+//! fn byte_arithmetic_operator() {
+//! let x = ByteSize::mb(1);
+//! let y = ByteSize::kb(100);
+//!
+//! let plus = x + y;
+//! print!("{} bytes", plus.as_u64());
+//!
+//! let minus = ByteSize::tb(100) - ByteSize::gb(4);
+//! print!("{} bytes", minus.as_u64());
+//! }
+//! ```
+//!
+//! It also provides its human readable string as follows:
+//!
+//! ```ignore=
+//! assert_eq!("482 GiB".to_string(), ByteSize::gb(518).to_string(true));
+//! assert_eq!("518 GB".to_string(), ByteSize::gb(518).to_string(false));
+//! ```
+
+#[cfg(feature = "serde")]
+#[macro_use]
+extern crate serde;
+
+use std::fmt::{Debug, Display, Formatter, Result};
+use std::ops::{Add, Mul};
+
+/// byte size for 1 byte
+pub const B: u64 = 1;
+/// bytes size for 1 kilobyte
+pub const KB: u64 = 1_000;
+/// bytes size for 1 megabyte
+pub const MB: u64 = 1_000_000;
+/// bytes size for 1 gigabyte
+pub const GB: u64 = 1_000_000_000;
+/// bytes size for 1 terabyte
+pub const TB: u64 = 1_000_000_000_000;
+/// bytes size for 1 petabyte
+pub const PB: u64 = 1_000_000_000_000_000;
+
+/// bytes size for 1 kibibyte
+pub const KIB: u64 = 1_024;
+/// bytes size for 1 mebibyte
+pub const MIB: u64 = 1_048_576;
+/// bytes size for 1 gibibyte
+pub const GIB: u64 = 1_073_741_824;
+/// bytes size for 1 tebibyte
+pub const TIB: u64 = 1_099_511_627_776;
+/// bytes size for 1 pebibyte
+pub const PIB: u64 = 1_125_899_906_842_624;
+
+static UNITS: &'static str = "KMGTPE";
+static UNITS_SI: &'static str = "kMGTPE";
+static LN_KB: f64 = 6.931471806; // ln 1024
+static LN_KIB: f64 = 6.907755279; // ln 1000
+
+pub fn kb<V: Into<u64>>(size: V) -> u64 {
+ size.into() * KB
+}
+
+pub fn kib<V: Into<u64>>(size: V) -> u64 {
+ size.into() * KIB
+}
+
+pub fn mb<V: Into<u64>>(size: V) -> u64 {
+ size.into() * MB
+}
+
+pub fn mib<V: Into<u64>>(size: V) -> u64 {
+ size.into() * MIB
+}
+
+pub fn gb<V: Into<u64>>(size: V) -> u64 {
+ size.into() * GB
+}
+
+pub fn gib<V: Into<u64>>(size: V) -> u64 {
+ size.into() * GIB
+}
+
+pub fn tb<V: Into<u64>>(size: V) -> u64 {
+ size.into() * TB
+}
+
+pub fn tib<V: Into<u64>>(size: V) -> u64 {
+ size.into() * TIB
+}
+
+pub fn pb<V: Into<u64>>(size: V) -> u64 {
+ size.into() * PB
+}
+
+pub fn pib<V: Into<u64>>(size: V) -> u64 {
+ size.into() * PIB
+}
+
+/// Byte size representation
+#[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Default)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+pub struct ByteSize(pub u64);
+
+impl ByteSize {
+ #[inline(always)]
+ pub fn b(size: u64) -> ByteSize {
+ ByteSize(size)
+ }
+
+ #[inline(always)]
+ pub fn kb(size: u64) -> ByteSize {
+ ByteSize(size * KB)
+ }
+
+ #[inline(always)]
+ pub fn kib(size: u64) -> ByteSize {
+ ByteSize(size * KIB)
+ }
+
+ #[inline(always)]
+ pub fn mb(size: u64) -> ByteSize {
+ ByteSize(size * MB)
+ }
+
+ #[inline(always)]
+ pub fn mib(size: u64) -> ByteSize {
+ ByteSize(size * MIB)
+ }
+
+ #[inline(always)]
+ pub fn gb(size: u64) -> ByteSize {
+ ByteSize(size * GB)
+ }
+
+ #[inline(always)]
+ pub fn gib(size: u64) -> ByteSize {
+ ByteSize(size * GIB)
+ }
+
+ #[inline(always)]
+ pub fn tb(size: u64) -> ByteSize {
+ ByteSize(size * TB)
+ }
+
+ #[inline(always)]
+ pub fn tib(size: u64) -> ByteSize {
+ ByteSize(size * TIB)
+ }
+
+ #[inline(always)]
+ pub fn pb(size: u64) -> ByteSize {
+ ByteSize(size * PB)
+ }
+
+ #[inline(always)]
+ pub fn pib(size: u64) -> ByteSize {
+ ByteSize(size * PIB)
+ }
+
+ #[inline(always)]
+ pub fn as_u64(&self) -> u64 {
+ self.0
+ }
+
+ #[inline(always)]
+ pub fn to_string_as(&self, si_unit: bool) -> String {
+ to_string(self.0, si_unit)
+ }
+}
+
+pub fn to_string(bytes: u64, si_prefix: bool) -> String {
+ let unit = if si_prefix { KIB } else { KB };
+ let unit_base = if si_prefix { LN_KIB } else { LN_KB };
+ let unit_prefix = if si_prefix {
+ UNITS_SI.as_bytes()
+ } else {
+ UNITS.as_bytes()
+ };
+ let unit_suffix = if si_prefix { "iB" } else { "B" };
+
+ if bytes < unit {
+ format!("{} B", bytes)
+ } else {
+ let size = bytes as f64;
+ let exp = match (size.ln() / unit_base) as usize {
+ e if e == 0 => 1,
+ e => e,
+ };
+
+ format!(
+ "{:.1} {}{}",
+ (size / unit.pow(exp as u32) as f64),
+ unit_prefix[exp - 1] as char,
+ unit_suffix
+ )
+ }
+}
+
+impl Display for ByteSize {
+ fn fmt(&self, f: &mut Formatter) -> Result {
+ f.pad(&to_string(self.0, false))
+ }
+}
+
+impl Debug for ByteSize {
+ fn fmt(&self, f: &mut Formatter) -> Result {
+ write!(f, "{}", self)
+ }
+}
+
+macro_rules! commutative_op {
+ ($t:ty) => {
+ impl Add<$t> for ByteSize {
+ type Output = ByteSize;
+ #[inline(always)]
+ fn add(self, rhs: $t) -> ByteSize {
+ ByteSize(self.0 + (rhs as u64))
+ }
+ }
+
+ impl Add<ByteSize> for $t {
+ type Output = ByteSize;
+ #[inline(always)]
+ fn add(self, rhs: ByteSize) -> ByteSize {
+ ByteSize(rhs.0 + (self as u64))
+ }
+ }
+
+ impl Mul<$t> for ByteSize {
+ type Output = ByteSize;
+ #[inline(always)]
+ fn mul(self, rhs: $t) -> ByteSize {
+ ByteSize(self.0 * (rhs as u64))
+ }
+ }
+
+ impl Mul<ByteSize> for $t {
+ type Output = ByteSize;
+ #[inline(always)]
+ fn mul(self, rhs: ByteSize) -> ByteSize {
+ ByteSize(rhs.0 * (self as u64))
+ }
+ }
+ };
+}
+
+commutative_op!(u64);
+commutative_op!(u32);
+commutative_op!(u16);
+commutative_op!(u8);
+
+impl Add<ByteSize> for ByteSize {
+ type Output = ByteSize;
+
+ #[inline(always)]
+ fn add(self, rhs: ByteSize) -> ByteSize {
+ ByteSize(self.0 + rhs.0)
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn test_arithmetic_op() {
+ let x = ByteSize::mb(1);
+ let y = ByteSize::kb(100);
+
+ assert_eq!((x + y).as_u64(), 1_100_000u64);
+
+ assert_eq!((x + (100 * 1000) as u64).as_u64(), 1_100_000);
+
+ assert_eq!((x * 2u64).as_u64(), 2_000_000);
+ }
+
+ #[test]
+ fn test_arithmetic_primitives() {
+ let x = ByteSize::mb(1);
+
+ assert_eq!((x + MB as u64).as_u64(), 2_000_000);
+
+ assert_eq!((x + MB as u32).as_u64(), 2_000_000);
+
+ assert_eq!((x + KB as u16).as_u64(), 1_001_000);
+
+ assert_eq!((x + B as u8).as_u64(), 1_000_001);
+ }
+
+ #[test]
+ fn test_comparison() {
+ assert!(ByteSize::mb(1) == ByteSize::kb(1000));
+ assert!(ByteSize::mib(1) == ByteSize::kib(1024));
+ assert!(ByteSize::mb(1) != ByteSize::kib(1024));
+ assert!(ByteSize::mb(1) < ByteSize::kib(1024));
+ assert!(ByteSize::b(0) < ByteSize::tib(1));
+ }
+
+ fn assert_display(expected: &str, b: ByteSize) {
+ assert_eq!(expected, format!("{}", b));
+ }
+
+ #[test]
+ fn test_display() {
+ assert_display("215 B", ByteSize::b(215));
+ assert_display("1.0 KB", ByteSize::kb(1));
+ assert_display("301.0 KB", ByteSize::kb(301));
+ assert_display("419.0 MB", ByteSize::mb(419));
+ assert_display("518.0 GB", ByteSize::gb(518));
+ assert_display("815.0 TB", ByteSize::tb(815));
+ assert_display("609.0 PB", ByteSize::pb(609));
+ }
+
+ #[test]
+ fn test_display_alignment() {
+ assert_eq!("|357 B |", format!("|{:10}|", ByteSize(357)));
+ assert_eq!("| 357 B|", format!("|{:>10}|", ByteSize(357)));
+ assert_eq!("|357 B |", format!("|{:<10}|", ByteSize(357)));
+ assert_eq!("| 357 B |", format!("|{:^10}|", ByteSize(357)));
+
+ assert_eq!("|-----357 B|", format!("|{:->10}|", ByteSize(357)));
+ assert_eq!("|357 B-----|", format!("|{:-<10}|", ByteSize(357)));
+ assert_eq!("|--357 B---|", format!("|{:-^10}|", ByteSize(357)));
+ }
+
+ fn assert_to_string(expected: &str, b: ByteSize, si: bool) {
+ assert_eq!(expected.to_string(), b.to_string_as(si));
+ }
+
+ #[test]
+ fn test_to_string_as() {
+ assert_to_string("215 B", ByteSize::b(215), true);
+ assert_to_string("215 B", ByteSize::b(215), false);
+
+ assert_to_string("1.0 kiB", ByteSize::kib(1), true);
+ assert_to_string("1.0 KB", ByteSize::kib(1), false);
+
+ assert_to_string("293.9 kiB", ByteSize::kb(301), true);
+ assert_to_string("301.0 KB", ByteSize::kb(301), false);
+
+ assert_to_string("1.0 MiB", ByteSize::mib(1), true);
+ assert_to_string("1048.6 KB", ByteSize::mib(1), false);
+
+ // a bug case: https://github.com/flang-project/bytesize/issues/8
+ assert_to_string("1.9 GiB", ByteSize::mib(1907), true);
+ assert_to_string("2.0 GB", ByteSize::mib(1908), false);
+
+ assert_to_string("399.6 MiB", ByteSize::mb(419), true);
+ assert_to_string("419.0 MB", ByteSize::mb(419), false);
+
+ assert_to_string("482.4 GiB", ByteSize::gb(518), true);
+ assert_to_string("518.0 GB", ByteSize::gb(518), false);
+
+ assert_to_string("741.2 TiB", ByteSize::tb(815), true);
+ assert_to_string("815.0 TB", ByteSize::tb(815), false);
+
+ assert_to_string("540.9 PiB", ByteSize::pb(609), true);
+ assert_to_string("609.0 PB", ByteSize::pb(609), false);
+ }
+
+ #[test]
+ fn test_default() {
+ assert_eq!(ByteSize::b(0), ByteSize::default());
+ }
+
+ #[test]
+ fn test_to_string() {
+ assert_to_string("609.0 PB", ByteSize::pb(609), false);
+ }
+}