Expand description
§prettier-bytes
A blazingly fast and safe, zero-allocation, no_std-compatible byte formatter.
prettier-bytes provides the API to format raw byte sizes into human-readable strings (e.g., “1.50 MB”, “2.34 GiB”) without using heap allocations, floating-point math, or dynamic CPU division. It is designed for maximum throughput in microcontrollers, OS kernels, and high-performance CLIs.
§✨ Features
- Zero Allocation: Operates entirely on a 16-byte stack array. It does not use the
alloccrate. - Mathematically Panic-Free: Built under a paranoid
#![forbid(...)]linting regime. Zero slice indexing, zerounwrap(), zeroexpect(). The compiler is mathematically guaranteed to never insert bounds-check panic branches. - Hardware Optimized: Bypasses incredibly slow 64-bit dynamic hardware division. It relies purely on 1-cycle bitwise shifts for Binary parsing, and compile-time reciprocal multiplication for SI parsing.
- 100% Safe Rust: Forbids
unsafecode entirely. no_stdNative: Works out of the box in bare-metal environments.
§🚀 Quick Start
use prettier_bytes::{ByteFormatter, Standard, Unit};
fn main() {
// Configure the formatter once
let formatter = ByteFormatter::new()
.standard(Standard::Binary)
.unit(Unit::Bytes)
.space(true);
// Format your value!
let size = formatter.format(1048576);
// Implements `fmt::Display` for zero-friction printing
println!("File size: {size}"); // Outputs: "1.00 MiB"
}§🛠 Usage & API
The ByteFormatter uses a builder pattern to configure your output. Once configured, you can call .format(value) to calculate the size and store it inside a tiny [u8; 16] buffer. You have full control over the standard, units, and spacing.
§Standards (SI vs Binary)
use prettier_bytes::{ByteFormatter, Standard};
let val = 2_500_000;
// Base 1000 (SI Standard) -> kB, MB, GB...
let si = ByteFormatter::new()
.standard(Standard::SI)
.format(val);
assert_eq!(si.as_str().unwrap(), "2.50 MB");
// Base 1024 (IEC/Binary Standard) -> KiB, MiB, GiB...
let bin = ByteFormatter::new()
.standard(Standard::Binary)
.format(val);
assert_eq!(bin.as_str().unwrap(), "2.38 MiB");§Units (Bytes vs Bits)
use prettier_bytes::{ByteFormatter, Standard, Unit};
let val = 2_500_000;
// Capital 'B' for Bytes
let bytes = ByteFormatter::new()
.standard(Standard::SI)
.unit(Unit::Bytes)
.format(val);
assert_eq!(bytes.as_str().unwrap(), "2.50 MB");
// Lowercase 'b' for Bits
let bits = ByteFormatter::new()
.standard(Standard::SI)
.unit(Unit::Bits)
.format(val);
assert_eq!(bits.as_str().unwrap(), "2.50 Mb");§Zero-Cost Retrievals
If you are writing to a fast I/O stream, you don’t even need to convert it to a string. You can extract the raw, formatted byte slice directly:
use prettier_bytes::{ByteFormatter, Standard, Unit};
let formatted = ByteFormatter::new()
.standard(Standard::SI)
.space(false)
.format(1500);
// Instantly returns &[u8] for fast std::io::Write or embedded UART transmission
let raw_bytes = formatted.as_bytes();
assert_eq!(raw_bytes, b"1.50kB");§🏎 Under the Hood: Why is it so fast?
Most “human readable byte” formatting libraries follow this pattern:
- Figure out the magnitude (Kilo, Mega, Giga).
- Look up the divisor in an array.
- Divide the value by the divisor dynamically at runtime (
val / divisor). - Append to a
String.
This is disastrous for performance. Array lookups risk bounds panics. Heap allocation (String) is slow. And worst of all, dynamic 64-bit division is one of the slowest operations a CPU can do, taking 15 to 40 clock cycles.
prettier-bytes flips this on its head:
- It uses purely static
matchstatements to figure out the magnitude. - For Binary (base 1024), it replaces division entirely with bitwise shifts (
>>) and masking (&), executing in a single clock cycle. - For SI (base 1000), it feeds hardcoded literals into a macro, allowing the LLVM compiler to replace division with lightning-fast “reciprocal multiplication”.
- It iterates safely over a stack-allocated
[u8; 16]to assemble the string.
The result is a completely flat, allocation-free assembly profile.
§⚖️ License
This project is licensed under the MIT License.
Structs§
- Byte
Formatter - A configurable formatter for byte sizes.
- Formatted
Bytes - A stack-allocated buffer containing the formatted byte string.