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 ;
🛠 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 ;
let val = 2_500_000;
// Base 1000 (SI Standard) -> kB, MB, GB...
let si = new
.standard
.format;
assert_eq!;
// Base 1024 (IEC/Binary Standard) -> KiB, MiB, GiB...
let bin = new
.standard
.format;
assert_eq!;
Units (Bytes vs Bits)
use ;
let val = 2_500_000;
// Capital 'B' for Bytes
let bytes = new
.standard
.unit
.format;
assert_eq!;
// Lowercase 'b' for Bits
let bits = new
.standard
.unit
.format;
assert_eq!;
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 ;
let formatted = new
.standard
.space
.format;
// Instantly returns &[u8] for fast std::io::Write or embedded UART transmission
let raw_bytes = formatted.as_bytes;
assert_eq!;
🏎 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.