byte-calc 0.1.0

Helper crate to work with bit, byte, and block sizes.
Documentation
  • Coverage
  • 96.67%
    58 out of 60 items documented1 out of 40 items with examples
  • Size
  • Source code size: 32.53 kB This is the summed size of all the files inside the crates.io package for this release.
  • Documentation size: 4.95 MB This is the summed size of all files generated by rustdoc for all configured targets
  • Ø build duration
  • this release: 9s Average build duration of successful builds.
  • all releases: 9s Average build duration of successful builds in releases after 2024-10-23.
  • Links
  • Homepage
  • rugix/rugix
    132 18 0
  • crates.io
  • Dependencies
  • Versions
  • Owners
  • koehlma

Helper crate to work with bit, byte, and block sizes.

This crate provides three dedicated types, [NumBits], [NumBytes], and [NumBlocks], to represent numbers of bits, bytes, and blocks, respectively. It implements the usual traits for numeric operators such that calculations on them can be carried out with succinct syntax. All operations will panic on errors, such as over- or underflows. This is an intentional design decision to prevent subtly incorrect results and behavior. In addition, this crate provides formatting and parsing for byte sizes.

This crate is no_std-compatible.

Conversions

The provided types support convenient conversions to each other:

# use byte_calc::{NumBits, NumBytes, NumBlocks};
assert_eq!(NumBits::new(15).to_bytes_ceil(), NumBytes::bytes(2));
assert_eq!(NumBits::new(15).to_bytes_floor(), NumBytes::bytes(1));

assert_eq!(NumBytes::bytes(2).to_bits(), NumBits::new(16));
assert_eq!(NumBits::from(NumBytes::bytes(2)), NumBits::new(16));

const BLOCK_SIZE: NumBytes = NumBytes::kibibytes(4);
assert_eq!(NumBytes::bytes(8193).to_blocks_ceil(BLOCK_SIZE), NumBlocks::new(3));
assert_eq!(NumBytes::bytes(8193).to_blocks_floor(BLOCK_SIZE), NumBlocks::new(2));

assert_eq!(NumBlocks::new(2).to_bytes(BLOCK_SIZE), NumBytes::kibibytes(8));

Calculations

Calculations can be performed with the types as well as with [u64] integers:

# use byte_calc::{NumBits, NumBytes, NumBlocks};
assert_eq!(NumBytes::bytes(10) / NumBytes::bytes(2), NumBytes::bytes(5));
assert_eq!(NumBytes::bytes(10) / 2, NumBytes::bytes(5));

assert_eq!(NumBits::new(5) + NumBits::new(8), NumBits::new(13));
assert_eq!(NumBits::new(5) * 2, NumBits::new(10));

assert_eq!(NumBlocks::new(10) + 2, NumBlocks::new(12));

assert_eq!(NumBits::new(2) + NumBytes::bytes(1), NumBits::new(10));

Comparisons

Comparisons are supported on the types as well as with [u64] integers:

# use byte_calc::{NumBits, NumBytes, NumBlocks};
assert!(NumBytes::bytes(10) < 20);
assert!(NumBytes::bytes(10) != 0);

assert_eq!(NumBits::new(5), 5);

assert_eq!(NumBits::new(16), NumBytes::new(2));
assert!(NumBits::new(15) < NumBytes::new(2));

Formatting

Formatting of byte sizes maximizes the unit while minimizing the integer part towards one. For example:

# use byte_calc::NumBytes;
assert_eq!(NumBytes::mebibytes(128).to_string(), "128MiB");
assert_eq!(NumBytes::gigabytes(1).to_string(), "1GB");
assert_eq!(NumBytes::bytes(1023).to_string(), "1.023kB");
assert_eq!(NumBytes::bytes(1000).to_string(), "1kB");
assert_eq!(NumBytes::bytes(999).to_string(), "999B");
assert_eq!(NumBytes::bytes(2560).to_string(), "2.5KiB");

The usual formatting syntax can be used to limit the precision:

# use byte_calc::NumBytes;
assert_eq!(format!("{:.2}", NumBytes::terabytes(2)), "1.81TiB");

Parsing

Byte sizes must follow the following syntax:

⟨byte-size⟩  ::=  ⟨int⟩ [ '.' ⟨int⟩ ] [ ' '* ⟨unit⟩ ]
⟨int⟩  ::=  [0-9_]+
⟨unit⟩ ::=  'B' | 'K' … 'E' | 'kB' … 'EB' | 'KiB' … 'EiB' (case-insensitive)

The units (K ... E) are interpreted as binary units (KiB ... EiB). Generally, unit parsing is case-insensitive.

# use core::str::FromStr;
# use byte_calc::NumBytes;
assert_eq!(NumBytes::from_str("5").unwrap(), NumBytes::bytes(5));
assert_eq!(NumBytes::from_str("2.5KiB").unwrap(), NumBytes::bytes(2560));
assert_eq!(NumBytes::from_str("2_000kB").unwrap(), NumBytes::megabytes(2));

Parsing also works in const contexts using [NumBytes::parse_str] or [NumBytes::parse_ascii]:

# use core::str::FromStr;
# use byte_calc::NumBytes;
const BLOCK_SIZE: NumBytes = match NumBytes::parse_str("4KiB") {
    Ok(value) => value,
    Err(_) => panic!("invalid format"),
};

The parser has been extensively fuzz-tested, ensuring that no input leads to panics.

Serialization and Deserialization

By enabling the serde feature, [NumBits], [NumBytes], and [NumBlocks] can be serialized and deserialized. All tree types always serialize as [u64] integers. Deserialization of [NumBytes] is also supported from strings.