Expand description
Panic-free, allocating byte→value transforms with no format knowledge.
The companion to safe-read: that crate is no_std with
no allocator and reads fixed-width integers; this one needs alloc because its
outputs are Strings and Vecs. That allocator boundary is the whole reason the two
are separate crates.
Membership is decidable — every function here is panic-free, allocating, format-agnostic, and free of domain knowledge. A transform that needs to know what the bytes mean belongs in the crate that owns that knowledge, not here.
§The UTF-16 family names its NUL policy
A fleet audit found fourteen hand-rolled UTF-16 decoders disagreeing about NUL in four
different ways. The disagreement was invisible because every one of them was called
decode_utf16le. Here each policy is a separately named function, so picking the wrong
one is a deliberate act rather than an accident:
use safe_decode::{
decode_utf16le_keep_nuls, decode_utf16le_trim_end_nuls, decode_utf16le_until_nul,
split_utf16le_on_nul,
};
// UTF-16LE for 'A', NUL, 'B', NUL — the same bytes, four correct answers.
let bytes = b"A\0\0\0B\0\0\0";
assert_eq!(decode_utf16le_keep_nuls(bytes).text, "A\0B\0");
assert_eq!(decode_utf16le_until_nul(bytes).text, "A");
assert_eq!(decode_utf16le_trim_end_nuls(bytes).text, "A\0B");
let parts = split_utf16le_on_nul(bytes);
let texts: Vec<&str> = parts.iter().map(|d| d.text.as_str()).collect();
assert_eq!(texts, ["A", "B", ""]);Each decode returns a DecodedUtf16, which carries whether information was lost and
why — an unpaired surrogate half, or an odd trailing byte that could not form a code
unit. A caller that ignores it still gets well-formed text; a caller that cares can say
so in a report.
use safe_decode::decode_utf16le_keep_nuls;
let lone_high_surrogate = decode_utf16le_keep_nuls(&[0x00, 0xD8]);
assert_eq!(lone_high_surrogate.text, "\u{FFFD}");
assert_eq!(lone_high_surrogate.unpaired_surrogates, 1);
assert!(lone_high_surrogate.is_lossy());Structs§
- Decoded
Utf16 - A decoded UTF-16 string together with what decoding it cost.
Functions§
- decode_
utf16be_ keep_ nuls - Decode the whole slice as UTF-16BE, keeping NUL code units as U+0000 characters.
- decode_
utf16be_ trim_ end_ nuls - Decode the whole slice as UTF-16BE, then strip NUL code units from the end only.
- decode_
utf16be_ until_ nul - Decode UTF-16BE up to the first NUL code unit, which terminates the string.
- decode_
utf16le_ keep_ nuls - Decode the whole slice as UTF-16LE, keeping NUL code units as U+0000 characters.
- decode_
utf16le_ trim_ end_ nuls - Decode the whole slice as UTF-16LE, then strip NUL code units from the end only.
- decode_
utf16le_ until_ nul - Decode UTF-16LE up to the first NUL code unit, which terminates the string.
- rot13
- Rotate every ASCII letter of
sby thirteen positions, wrapping within its own case. - split_
utf16be_ on_ nul - Split a UTF-16BE slice on NUL code units and decode every segment.
- split_
utf16le_ on_ nul - Split a UTF-16LE slice on NUL code units and decode every segment.
- to_
hex_ lower - Render
bytesas lowercase hex, two characters per byte, no separator. - to_
hex_ upper - Render
bytesas uppercase hex, two characters per byte, no separator.