ryu
Fast, allocation-free floating point to string conversion for Rust, implementing the Ryu algorithm.
Repository Health
Technical Analysis
Ryu is a pure Rust, line-by-line port of Ulf Adams’ C reference implementation of the Ryu algorithm from his PLDI’18 paper, which converts IEEE 754 floating point numbers (f32/f64) to the shortest decimal string representation that round-trips back to the exact same value. It exposes both a safe Buffer API that writes into a stack-allocated buffer and returns a &str, and an unsafe raw module (format32/format64) that mirrors the upstream C API for callers who want to skip the safe wrapper.
The crate is #![no_std] and allocation-free, formatting directly into a fixed 24-byte stack buffer, which makes it usable in embedded and kernel-level contexts as well as ordinary applications. An optional small feature trades a modest amount of performance for roughly 10x smaller static lookup tables. Benchmarks show Ryu formatting floats around 2-5x faster than the Rust standard library’s to_string, and the crate is validated with fuzzing, Miri across multiple target endianness/word-size combinations, and no-panic-verified builds.
What You Get
- A safe
Buffertype withformat/format_finitemethods that return a&strview into a reusable stack buffer - An unsafe
rawmodule (format32,format64) mirroring the upstream C API for callers who want to bypass the safe wrapper no_stdand allocation-free operation, formatting into a fixed 24-byte stack buffer, suitable for embedded and kernel contexts- An optional
smallfeature flag that shrinks the static lookup tables roughly 10x at a modest performance cost - Special-case handling for NaN,
inf, and-infmatchingstd::fmtconventions in the safeformatmethod
Common Use Cases
- Formatting floats inside JSON and other data-serialization libraries
- Fast numeric output in logging, telemetry, and protocol encoders
- Embedded or no_std environments that need float-to-string conversion without heap allocation
- Any hot path where the standard library’s
to_stringfor floats is a measurable bottleneck
Under The Hood
Architecture
Ryu splits float formatting into f2s.rs (32-bit) and d2s.rs (64-bit) core algorithm modules, each paired with an intrinsics module (f2s_intrinsics.rs, d2s_intrinsics.rs) for the fixed-point multiply/shift math, and a table module (d2s_full_table.rs, or d2s_small_table.rs when the small feature is enabled) holding precomputed powers of five. The pretty module (mantissa.rs, exponent.rs, mod.rs) turns the raw digit/exponent output from d2s/f2s into human-readable decimal or scientific notation, and buffer/mod.rs is the sole public-facing layer, wrapping the unsafe raw::format32/format64 calls in a safe Buffer struct backed by a stack [MaybeUninit<u8>; 24]. common.rs holds shared bit-manipulation helpers and digit_table.rs a shared two-digit ASCII lookup table. This is a strictly layered pipeline — bit decomposition, then digit generation, then pretty-printing, then the safe buffer wrapper — where a change to the core d2s/f2s algorithm would ripple through every layer above it, but the module boundaries are narrow enough that a new output format would only touch pretty/.
Tech Stack
Pure Rust, edition 2021, MSRV 1.71, #![no_std] with no required runtime dependencies beyond an optional no-panic crate used to statically verify panic-freedom. Dev-dependencies exist solely for testing and benchmarking: rand/rand_core/rand_xorshift for randomized test inputs, criterion for benchmarking, and num_cpus for parallelizing exhaustive tests. build.rs only emits cargo:rustc-check-cfg directives, with no code generation. CI runs the test suite across nightly, beta, stable, and the MSRV toolchain, plus dedicated Miri jobs spanning four target endianness/word-size combinations, a cargo fuzz check job, and a cargo clippy --tests --benches -Dclippy::pedantic lint gate.
Code Quality
Tests are extensive: the tests/ directory holds dedicated suites for d2s, f2s, s2d, s2f, intrinsics, and lookup tables, plus an exhaustive.rs for brute-force coverage and a shared macros/ test-helper crate; src/tests.rs even asserts the exact byte size of the static lookup tables at compile time. There is no traditional error-handling surface since the crate performs pure computation with no I/O, but the public API is designed to never panic, and a nightly CI job builds the test suite under the no-panic crate to enforce that statically. Fuzzing via cargo-fuzz and Miri (across multiple target configurations with strict-provenance flags) both run in CI, which is unusually rigorous for a crate of this size, and clippy’s pedantic lint set is enforced rather than merely suggested.
What Makes It Unique
Ryu’s core algorithm isn’t Rust-specific — it’s a faithful, unsafe-for-speed port of Ulf Adams’ PLDI’18 Ryu algorithm, which guarantees shortest round-tripping decimal output while running considerably faster than typical Grisu/Dragon-style formatters. Within the Rust ecosystem specifically, it stands out for combining no_std/allocation-free operation (letting it run in kernels and firmware) with no-panic-verified builds, a combination few numeric-formatting crates offer, and it underlies the float formatting used by other prominent Rust serialization crates.