hex

Encode and decode data to and from hexadecimal in Rust, with no_std and serde support.

Library
Cargo
v0.4.3
272 stars
Apache License 2.0

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum. How we score it →
36 /100 Needs Attention
Development Activity 0
Maintenance 0
Community 64
Maturity 60
Momentum 20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation. How we score it →
89 /100 Excellent
Architecture 82
Code Quality 90
Innovation 88
Learning Curve 95

hex is a small, dependency-light Rust crate for converting bytes to and from their hexadecimal string representation. Originally extracted from rustc-serialize, it exposes simple top-level encode/decode functions for the common case plus the ToHex and FromHex traits when you need finer control over allocation and output types.

The crate is #![forbid(unsafe_code)] and works in no_std environments through configurable std, alloc, and serde feature flags, making it suitable for everything from application code to embedded targets. It also provides slice-based APIs that let you encode and decode without heap allocation.

What You Get

  • Top-level encode, encode_upper, and decode helpers for the common string case
  • ToHex and FromHex traits implemented for any AsRef<[u8]> and for Vec<u8>/[u8; N]
  • Allocation-free encode_to_slice and decode_to_slice APIs for fixed buffers and no_std
  • Optional serde integration via #[serde(with = "hex")] for de/serializing byte fields
  • A precise FromHexError enum distinguishing invalid characters, odd length, and bad buffer size

Common Use Cases

  • Rendering binary data such as hashes, keys, or checksums as readable hex strings
  • Parsing hex-encoded input from config files, CLIs, or wire formats back into bytes
  • Serializing Vec<u8> fields as hex in JSON and other serde-driven formats
  • Encoding and decoding on embedded or no_std targets without heap allocation

Under The Hood

Architecture

The crate is a single flat module in src/lib.rs with two supporting files, src/error.rs (the FromHexError enum) and src/serde.rs (optional serde glue). Encoding is driven by a BytesToHexChars iterator that walks a byte slice, splitting each byte into high and low nibbles and indexing a static 16-entry lookup table (HEX_CHARS_LOWER/HEX_CHARS_UPPER); it implements ExactSizeIterator so encode can preallocate the output String. Decoding maps each ASCII hex character back to a nibble via val() and recombines pairs, surfacing structured errors for invalid characters, odd input length, or mismatched fixed-buffer sizes. Public entry points layer from the ergonomic encode/decode free functions down to the ToHex/FromHex traits and the allocation-free encode_to_slice/decode_to_slice variants.

Tech Stack

Pure Rust on the 2018 edition with an MSRV of 1.85 and no required runtime dependencies. serde (v1.0) is the only optional dependency, gated behind the serde feature. Feature flags form a small lattice — default = ["std"], std = ["alloc"], and standalone alloc and serde — so the crate degrades cleanly from full std down to no_std. Dev-dependencies (criterion, data-encoding, rustc-hex, faster-hex, version-sync, pretty_assertions, serde_json) drive benchmarks against competing crates and version-consistency checks.

Code Quality

High. The crate is #![forbid(unsafe_code)] and #![cfg_attr(not(feature = "std"), no_std)], and its public API is thoroughly documented with runnable doctests. Tests live inline in src/lib.rs and src/error.rs plus integration tests in tests/serde.rs and a version-sync check in tests/version-number.rs, covering round-trips, odd-length and invalid-character errors, empty input, whitespace rejection, and fixed-array decoding. Error handling is explicit through the FromHexError enum rather than panics, and naming (encode_to_slice, decode_to_slice, encode_upper) is consistent and predictable.

API Design

Excellent developer experience. The one-liner hex::encode/hex::decode functions cover the majority of use cases with zero boilerplate, while the ToHex/FromHex traits — blanket-implemented for any AsRef<[u8]> and for Vec<u8>/[u8; N] — give power users control over output type and allocation. The slice-based APIs support no_std and hot paths, and serde integration is a single #[serde(with = "hex")] attribute. Documentation is published on docs.rs with clear examples, making the crate approachable within minutes.

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