radix

Zero-dependency Rust crate for converting numbers between radices 2 through 36, with a typed, lossless string representation.

Library
Cargo
v0.6.0
3stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
18/100Needs Attention
Development Activity0
Maintenance0
Community12
Maturity60
Momentum0

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
50/100Fair
Architecture55
Code Quality60
Innovation45
Learning Curve40

radix is a small, dependency-free Rust crate for converting unsigned integers between number bases from 2 to 36. It defines a single RadixNum enum with one variant per supported radix, so a value’s base travels with its type instead of being tracked separately by the caller.

The crate covers the common conversion paths: parsing a string in an arbitrary radix, re-encoding a value into a different radix, formatting with the conventional 0b/0/0x prefixes for bases 2, 8, and 16, and iterating over a number’s individual digits. All of Rust’s unsigned integer primitives (u8 through u128, usize) convert into a RadixNum via the standard From trait.

What You Get

  • RadixNum enum - one variant per supported radix (2 through 36), each wrapping the digit string for that base
  • Bidirectional conversion - from_str parses a string in a given radix; with_radix re-encodes an existing value into a different radix
  • Idiomatic Display formatting - prints with 0b, 0, or 0x prefixes for binary, octal, and hex respectively, and a <digits>r<radix> form for every other base
  • Digit iteration - digits() returns an iterator over a number’s individual characters for custom rendering or analysis
  • From impls for every unsigned integer type - u8, u16, u32, u64, u128, and usize all convert into a base-10 RadixNum for free

Common Use Cases

  • Base conversion utilities - a CLI or library needs to accept numbers in hex/octal/binary and print them back out in another base
  • Custom numeral systems - encoding IDs or tokens in a non-standard radix (e.g. base 32 or base 36) for compact string representation
  • Teaching and demo tools - illustrating positional numeral systems and radix arithmetic in an educational context
  • Debug and log formatting - rendering integers in hex or binary for logs and diagnostics using the crate’s Display impl

Under The Hood

Architecture The crate is a single file (src/lib.rs) exposing a public RadixNum enum with one variant per supported radix (Radix2 through Radix36), a RadixErr error enum, and a handful of private helpers (validate_radix, validate_base, dec_to_radix_x, radix_x_to_dec). Every conversion funnels through decimal as an intermediate representation: from_str parses a string into decimal via radix_x_to_dec, then with_radix walks it back out to the target base via dec_to_radix_x. There is no I/O, no external state, and no dependency injection — just pure, deterministic string transformations. The one architectural rigidity is the one-variant-per-radix design: adding a new base or a signed representation means touching every exhaustive match arm across with_radix, radix, and as_str.

Tech Stack Cargo.toml declares zero dependencies beyond the Rust standard library, targeting the 2018 edition on Rust >= 1.26. There is no build script and no external crates used even for testing — tests rely purely on std assertions inside an inline #[cfg(test)] module. CI is a single GitHub Actions workflow (.github/workflows/rust.yml) that runs cargo build --verbose and cargo test --verbose on push against ubuntu-latest. There is no publish/release automation and no committed Cargo.lock, which is correct convention for a library crate.

Code Quality Tests live inline in src/lib.rs and are extensive for the crate’s scope: every supported radix from 2 through 36 has its own dedicated test converting a fixed set of decimal inputs and asserting the exact digit string, plus explicit tests for rejected radices (0, 1, 37) and empty/invalid input. There are no integration tests, no doctests beyond the module-level doc comment, and no linter or formatter configuration committed to the repo, nor a lint step in CI. Error handling in the public API is explicit and typed via RadixErr (which implements std::error::Error and Display) rather than panics, and internal helpers propagate errors with ? rather than .unwrap().

API Design The public surface is small and easy to learn: a single RadixNum type with from_str, with_radix, as_str, as_decimal, digits, and radix methods, plus From impls for every unsigned integer primitive so RadixNum::from(255u8) works without any ceremony. Display mirrors Rust’s own integer-literal conventions by prefixing binary/octal/hex output with 0b/0/0x. The tradeoffs are that encoding the radix into the enum variant means the type can’t represent an arbitrary runtime radix without an exhaustive match, there is no direct conversion between two non-decimal radices without passing through decimal, and the crate hasn’t been touched since 2019 — a modern rewrite would likely collapse the 36 enum variants into a single newtype carrying the radix as data.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search