1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
//! Panic-free, allocating byte→value transforms with no format knowledge.
//!
//! The companion to [`safe-read`](https://docs.rs/safe-read): that crate is `no_std` with
//! *no* allocator and reads fixed-width integers; this one needs `alloc` because its
//! outputs are `String`s and `Vec`s. 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());
//! ```
extern crate alloc;
pub use ;
pub use rot13;
pub use ;