Skip to main content

Crate faster_hex

Crate faster_hex 

Source
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 taskAPI
Encode into a byte bufferhex_encode, hex_encode_upper
Decode into a byte bufferhex_decode, hex_decode_with_case
Decode an exact-length arrayhex_decode_array, hex_decode_array_with_case
Format borrowed bytes into textHex with Display, LowerHex or UpperHex
Check characters without decodinghex_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.

FeatureProvides
NoneSlice and fixed-array conversion, borrowed formatting, and core::error::Error
allocOwned strings and byte vectors; appending to strings
stdalloc and standard-library support in enabled dependencies
serdeSerde adapters and alloc; also works without std
heapless-08Fixed-capacity strings using heapless 0.8, without requiring alloc
defmt-03defmt 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:

ModulePrefixSerializationAccepted letters
withpfx_ignorecase (default)0xLowercaseEither case
nopfx_ignorecaseNoneLowercaseEither case
withpfx_lowercase0xLowercaseLowercase
nopfx_lowercaseNoneLowercaseLowercase
withpfx_uppercase0xUppercaseUppercase
nopfx_uppercaseNoneUppercaseUppercase

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§

arrayserde
Exact-length arrays using the parent module’s prefix and case policy.
heapless_08heapless-08
Fixed-capacity strings using heapless 0.8.
nopfx_ignorecaseserde
Lowercase serialization without a prefix; accepts either letter case. Use #[serde(with = "...")] for byte collections. Serialization reads one [AsRef<[u8]>] view; deserialization collects into FromIterator<u8> after validating the complete input. All formats use strings, including binary formats.
nopfx_lowercaseserde
Lowercase hex without a prefix. Use #[serde(with = "...")] for byte collections. Serialization reads one [AsRef<[u8]>] view; deserialization collects into FromIterator<u8> after validating the complete input. All formats use strings, including binary formats.
nopfx_uppercaseserde
Uppercase hex without a prefix. Use #[serde(with = "...")] for byte collections. Serialization reads one [AsRef<[u8]>] view; deserialization collects into FromIterator<u8> after validating the complete input. All formats use strings, including binary formats.
option_nopfx_ignorecaseserde
Lowercase serialization without a prefix; accepts either letter case. Optional values. Present values follow nopfx_ignorecase. Absent values use Serde’s None representation (null in JSON). Binary formats retain their normal Option tags, so Some(empty) remains distinct from None.
option_nopfx_lowercaseserde
Lowercase hex without a prefix. Optional values. Present values follow nopfx_lowercase. Absent values use Serde’s None representation (null in JSON). Binary formats retain their normal Option tags, so Some(empty) remains distinct from None.
option_nopfx_uppercaseserde
Uppercase hex without a prefix. Optional values. Present values follow nopfx_uppercase. Absent values use Serde’s None representation (null in JSON). Binary formats retain their normal Option tags, so Some(empty) remains distinct from None.
option_withpfx_ignorecaseserde
Lowercase serialization with a 0x prefix; accepts either letter case. Optional values. Present values follow withpfx_ignorecase. Absent values use Serde’s None representation (null in JSON). Binary formats retain their normal Option tags, so Some(empty) remains distinct from None.
option_withpfx_lowercaseserde
Lowercase hex with a required 0x prefix. Optional values. Present values follow withpfx_lowercase. Absent values use Serde’s None representation (null in JSON). Binary formats retain their normal Option tags, so Some(empty) remains distinct from None.
option_withpfx_uppercaseserde
Uppercase hex with a required 0x prefix. Optional values. Present values follow withpfx_uppercase. Absent values use Serde’s None representation (null in JSON). Binary formats retain their normal Option tags, so Some(empty) remains distinct from None.
withpfx_ignorecaseserde
Lowercase serialization with a 0x prefix; accepts either letter case. Use #[serde(with = "...")] for byte collections. Serialization reads one [AsRef<[u8]>] view; deserialization collects into FromIterator<u8> after validating the complete input. All formats use strings, including binary formats.
withpfx_lowercaseserde
Lowercase hex with a required 0x prefix. Use #[serde(with = "...")] for byte collections. Serialization reads one [AsRef<[u8]>] view; deserialization collects into FromIterator<u8> after validating the complete input. All formats use strings, including binary formats.
withpfx_uppercaseserde
Uppercase hex with a required 0x prefix. Use #[serde(with = "...")] for byte collections. Serialization reads one [AsRef<[u8]>] view; deserialization collects into FromIterator<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§

CheckCase
Which ASCII letter cases are accepted when checking or decoding hex.
Error
An error from checked hexadecimal encoding or decoding.

Functions§

deserializeserde
Deserializes a 0x-prefixed hex string into a byte collection.
deserialize_boundedserde
Deserializes at most MAX decoded bytes from a 0x-prefixed hex string.
hex_appendalloc
Appends lowercase hexadecimal digits to dst and returns the appended suffix.
hex_append_upperalloc
Appends uppercase hexadecimal digits to dst and 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 src into dst without allocation, accepting either letter case.
hex_decode_array
Decodes exactly N bytes into an array without allocation, accepting either case.
hex_decode_array_with_case
Decodes exactly N bytes into an array using an explicit letter-case policy.
hex_decode_vecalloc
Decodes the complete input into a new vector, accepting either letter case.
hex_decode_vec_with_casealloc
Decodes the complete input into a new vector using a letter-case policy.
hex_decode_with_case
Decodes all of src into dst using an explicit letter-case policy.
hex_encode
Encodes all of src as lowercase hex into dst without allocation.
hex_encode_upper
Encodes all of src as uppercase hex into dst without allocation.
hex_stringalloc
Encodes src as an owned lowercase hexadecimal string.
hex_string_upperalloc
Encodes src as an owned uppercase hexadecimal string.
serializeserde
Serializes a byte view as lowercase hex with a 0x prefix.