safe-decode — Purpose & Scope¶
What it is. safe-decode is the fleet's single implementation of the
byte-to-value transforms that need an allocator: ROT13, the UTF-16 decoder family,
and hex rendering. Nothing here knows what the bytes mean. Every function is
panic-free on any input, and every UTF-16 decode reports whether it lost
information rather than handing back a plausible-looking string.
Who uses it. Any fleet crate that turns bytes into text. It exists because a
DRY audit found ROT13 implemented four times and UTF-16 decoded fourteen times,
the latter with four mutually incompatible NUL policies all sharing the name
decode_utf16le — a defect class that is invisible at every call site.
In scope. A transform qualifies only if it is panic-free, allocating,
format-agnostic, and free of domain knowledge — all four. #![no_std] plus
alloc, zero dependencies, #![forbid(unsafe_code)], and a low CI-verified MSRV
(1.75) so no consumer's floor is raised.
The boundary with safe-read. safe-read is no_std with no allocator; its
outputs are integers. This crate's outputs are Strings and Vecs, so it needs
alloc. That is not a stylistic split — it is why the UTF-16 decoders could not
simply be added to safe-read, and it is the membership line between the two.
Out of scope (someone else's job).
- Temporal conversion. FILETIME, WebKit and Unix epochs, and every sentinel
policy around them, belong to
timeglyph-core. One home for time. - Format conventions dressed as encodings.
REG_MULTI_SZ's double-NUL terminator andMRUListEx's0xFFFFFFFFsentinel are Windows registry facts, not properties of UTF-16 or of au32array. This crate supplies the structural half (split_utf16le_on_nul); the convention stays with the crate that owns the fact. - Anything needing a format catalog, and anything with its own crate (ESE, protobuf, LEB128 varints as defined by a specific format).
- Semantic validation. A
safe-decodecall guarantees "no panic, and an honest account of what was lost". It does not guarantee the bytes were a well-formed instance of anything.
Deliberately no default. There is no plain decode_utf16le, and no policy
enum or flag parameter. A caller must name the NUL policy it wants. The audit
showed that a shared, unqualified name is precisely what let four incompatible
behaviours coexist unnoticed for years.