Expand description
Hexadecimal encoding, decoding and formatting for byte sequences.
The core operations write into caller-provided buffers without allocating. SIMD implementations are selected internally where available; a portable scalar implementation provides the same behavior on other targets.
§Getting started
use faster_hex::{hex_decode, hex_encode};
let mut encoded = [0; 10];
let text = hex_encode(b"hello", &mut encoded)?;
assert_eq!(text, "68656c6c6f");
let mut decoded = [0; 5];
assert_eq!(hex_decode(text.as_bytes(), &mut decoded)?, b"hello");§Choosing an operation
| Destination or task | API |
|---|---|
| Encode into a byte buffer | hex_encode, hex_encode_upper |
| Decode into a byte buffer | hex_decode, hex_decode_with_case |
| Decode an exact-length array | hex_decode_array, hex_decode_array_with_case |
| Format borrowed bytes into text | Hex with Display, LowerHex or UpperHex |
| Check characters without decoding | hex_check, hex_check_with_case |
With alloc, hex_string and hex_string_upper create owned strings;
hex_append and hex_append_upper reuse a string’s capacity;
hex_decode_vec and hex_decode_vec_with_case create owned byte vectors.
The heapless-08 feature provides fixed-capacity strings in heapless_08.
§Conversion contracts
Encoding writes two ASCII digits per input byte. Decoding consumes the complete
input and requires an even number of ASCII hex digits. Both preserve leading
zeroes and byte order; neither treats the input as an integer. Slice and owned
decoders reject 0x prefixes, whitespace, separators and non-ASCII characters.
Serde adapters have their own explicit prefix policies.
Successful slice conversions return exactly the written prefix, borrowing only the destination. Extra destination capacity remains unchanged. Empty inputs succeed. Every slice conversion error preserves the entire destination, even when invalid input occurs after a long valid prefix.
Error exposes byte positions and required or exact lengths. Slice decoding
checks odd input, destination capacity, then characters. Array decoding checks
odd input, exact decoded length, then characters. Each function documents its
full error contract. hex_check checks characters only and can accept odd
lengths; checked decoders already perform validation, so a preceding check is
unnecessary.
§Crate features
Features are additive. The defaults are std and serde. With defaults disabled
and no optional features, the crate has no dependencies and needs neither an
allocator nor the standard library.
| Feature | Provides |
|---|---|
| None | Slice and fixed-array conversion, borrowed formatting, and core::error::Error |
alloc | Owned strings and byte vectors; appending to strings |
std | alloc and standard-library support in enabled dependencies |
serde | Serde adapters and alloc; also works without std |
heapless-08 | Fixed-capacity strings using heapless 0.8, without requiring alloc |
defmt-03 | defmt formatting for errors and case policies |
For example, enable Serde without the standard library:
[dependencies]
faster-hex = { version = "1", default-features = false, features = ["serde"] }§Platforms
On x86 and x86-64, implementations use SSE4.1, AVX2 and, for checking and decoding, AVX-512BW. Runtime detection checks CPU and operating-system support for features not enabled at compile time. AArch64 targets that guarantee NEON use it directly. Other configurations use the portable fallback. Backend selection, SIMD thresholds and instruction sequences are implementation details; no public backend selection or architecture-specific call is required.
The minimum supported Rust version is 1.95.0 throughout the 1.0.x line.
§Owned output and capacity reuse
hex_decode_vec returns owned decoded bytes; hex_string returns owned
text. hex_append preserves existing text and returns only its new suffix.
These functions follow the allocator’s normal error handling. Allocation failures
are not codec errors.
use faster_hex::{hex_append, hex_decode_vec};
let bytes = hex_decode_vec(b"00aB")?;
let mut text = String::with_capacity(64);
text.push_str("id: ");
assert_eq!(hex_append(&bytes, &mut text), "00ab");
assert_eq!(text, "id: 00ab");§Serde adapters
The default #[serde(with = "faster_hex")] adapter writes lowercase hex with a
0x prefix and accepts either letter case when reading. A required prefix is
exactly 0x, never 0X. Named modules select the wire policy:
| Module | Prefix | Serialization | Accepted letters |
|---|---|---|---|
withpfx_ignorecase (default) | 0x | Lowercase | Either case |
nopfx_ignorecase | None | Lowercase | Either case |
withpfx_lowercase | 0x | Lowercase | Lowercase |
nopfx_lowercase | None | Lowercase | Lowercase |
withpfx_uppercase | 0x | Uppercase | Uppercase |
nopfx_uppercase | None | Uppercase | Uppercase |
Each policy also has an option_ counterpart, an array submodule, and a
deserialize_bounded function. Present byte values use strings, including in
binary formats. Option adapters preserve the format’s Some/None tags; an empty
present value stays distinct from None. For missing struct fields, add
#[serde(default)] alongside the with attribute.
Use array for exact-length arrays. Generic adapters instead
collect into FromIterator<u8> containers; bounded
collectors can panic when full. deserialize_bounded limits decoded bytes before output allocation,
but does not bound the format’s input storage or a custom collector’s allocations.
#[derive(Debug, PartialEq, serde::Serialize, serde::Deserialize)]
struct Record {
#[serde(with = "faster_hex::array")]
id: [u8; 2],
#[serde(default, with = "faster_hex::option_nopfx_lowercase::array")]
extra: Option<[u8; 2]>,
}
let record = Record { id: [0xab, 1], extra: Some([0xcd, 2]) };
let json = serde_json::to_string(&record)?;
assert_eq!(json, r#"{"id":"0xab01","extra":"cd02"}"#);
assert_eq!(serde_json::from_str::<Record>(&json)?, record);
assert_eq!(serde_json::from_str::<Record>(r#"{"id":"0xab01"}"#)?.extra, None);Modules§
- array
serde - Exact-length arrays using the parent module’s prefix and case policy.
- heapless_
08 heapless-08 - Fixed-capacity strings using
heapless0.8. - nopfx_
ignorecase serde - Lowercase serialization without a prefix; accepts either letter case.
Use
#[serde(with = "...")]for byte collections. Serialization reads one [AsRef<[u8]>] view; deserialization collects intoFromIterator<u8>after validating the complete input. All formats use strings, including binary formats. - nopfx_
lowercase serde - Lowercase hex without a prefix.
Use
#[serde(with = "...")]for byte collections. Serialization reads one [AsRef<[u8]>] view; deserialization collects intoFromIterator<u8>after validating the complete input. All formats use strings, including binary formats. - nopfx_
uppercase serde - Uppercase hex without a prefix.
Use
#[serde(with = "...")]for byte collections. Serialization reads one [AsRef<[u8]>] view; deserialization collects intoFromIterator<u8>after validating the complete input. All formats use strings, including binary formats. - option_
nopfx_ ignorecase serde - Lowercase serialization without a prefix; accepts either letter case. Optional values.
Present values follow
nopfx_ignorecase. Absent values use Serde’sNonerepresentation (nullin JSON). Binary formats retain their normalOptiontags, soSome(empty)remains distinct fromNone. - option_
nopfx_ lowercase serde - Lowercase hex without a prefix. Optional values.
Present values follow
nopfx_lowercase. Absent values use Serde’sNonerepresentation (nullin JSON). Binary formats retain their normalOptiontags, soSome(empty)remains distinct fromNone. - option_
nopfx_ uppercase serde - Uppercase hex without a prefix. Optional values.
Present values follow
nopfx_uppercase. Absent values use Serde’sNonerepresentation (nullin JSON). Binary formats retain their normalOptiontags, soSome(empty)remains distinct fromNone. - option_
withpfx_ ignorecase serde - Lowercase serialization with a 0x prefix; accepts either letter case. Optional values.
Present values follow
withpfx_ignorecase. Absent values use Serde’sNonerepresentation (nullin JSON). Binary formats retain their normalOptiontags, soSome(empty)remains distinct fromNone. - option_
withpfx_ lowercase serde - Lowercase hex with a required 0x prefix. Optional values.
Present values follow
withpfx_lowercase. Absent values use Serde’sNonerepresentation (nullin JSON). Binary formats retain their normalOptiontags, soSome(empty)remains distinct fromNone. - option_
withpfx_ uppercase serde - Uppercase hex with a required 0x prefix. Optional values.
Present values follow
withpfx_uppercase. Absent values use Serde’sNonerepresentation (nullin JSON). Binary formats retain their normalOptiontags, soSome(empty)remains distinct fromNone. - withpfx_
ignorecase serde - Lowercase serialization with a 0x prefix; accepts either letter case.
Use
#[serde(with = "...")]for byte collections. Serialization reads one [AsRef<[u8]>] view; deserialization collects intoFromIterator<u8>after validating the complete input. All formats use strings, including binary formats. - withpfx_
lowercase serde - Lowercase hex with a required 0x prefix.
Use
#[serde(with = "...")]for byte collections. Serialization reads one [AsRef<[u8]>] view; deserialization collects intoFromIterator<u8>after validating the complete input. All formats use strings, including binary formats. - withpfx_
uppercase serde - Uppercase hex with a required 0x prefix.
Use
#[serde(with = "...")]for byte collections. Serialization reads one [AsRef<[u8]>] view; deserialization collects intoFromIterator<u8>after validating the complete input. All formats use strings, including binary formats.
Structs§
- Hex
- A borrowed hexadecimal view of a byte slice, available without allocation.
Enums§
- Check
Case - Which ASCII letter cases are accepted when checking or decoding hex.
- Error
- An error from checked hexadecimal encoding or decoding.
Functions§
- deserialize
serde - Deserializes a
0x-prefixed hex string into a byte collection. - deserialize_
bounded serde - Deserializes at most
MAXdecoded bytes from a0x-prefixed hex string. - hex_
append alloc - Appends lowercase hexadecimal digits to
dstand returns the appended suffix. - hex_
append_ upper alloc - Appends uppercase hexadecimal digits to
dstand returns the appended suffix. - hex_
check - Returns whether every byte is an ASCII hex digit, accepting either letter case.
- hex_
check_ with_ case - Checks ASCII hex digits against an explicit letter-case policy.
- hex_
decode - Decodes all of
srcintodstwithout allocation, accepting either letter case. - hex_
decode_ array - Decodes exactly
Nbytes into an array without allocation, accepting either case. - hex_
decode_ array_ with_ case - Decodes exactly
Nbytes into an array using an explicit letter-case policy. - hex_
decode_ vec alloc - Decodes the complete input into a new vector, accepting either letter case.
- hex_
decode_ vec_ with_ case alloc - Decodes the complete input into a new vector using a letter-case policy.
- hex_
decode_ with_ case - Decodes all of
srcintodstusing an explicit letter-case policy. - hex_
encode - Encodes all of
srcas lowercase hex intodstwithout allocation. - hex_
encode_ upper - Encodes all of
srcas uppercase hex intodstwithout allocation. - hex_
string alloc - Encodes
srcas an owned lowercase hexadecimal string. - hex_
string_ upper alloc - Encodes
srcas an owned uppercase hexadecimal string. - serialize
serde - Serializes a byte view as lowercase hex with a
0xprefix.