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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
//! Input normalization: Unicode NFC, whitespace trimming, email case normalization.
use UnicodeNormalization;
/// Normalizes a string to Unicode NFC (Canonical Decomposition, followed by Canonical Composition).
///
/// Ensures consistent representation of composed vs decomposed Unicode characters,
/// preventing normalization-based injection attacks.
///
/// # Examples
///
/// ```
/// use secure_boundary::normalize::to_nfc;
///
/// // Composed and decomposed forms are normalised to the same output.
/// let result = to_nfc("caf\u{00e9}"); // 'é' precomposed
/// assert_eq!(result, "café");
/// ```
/// Trims leading and trailing ASCII whitespace from a string.
///
/// # Examples
///
/// ```
/// use secure_boundary::normalize::trim_whitespace;
///
/// assert_eq!(trim_whitespace(" hello "), "hello");
/// ```
/// Normalizes an email address: trims whitespace and lowercases the domain portion.
///
/// Per RFC 5321, only the domain portion is case-insensitive. The local part
/// (before `@`) is preserved as-is.
///
/// # Examples
///
/// ```
/// use secure_boundary::normalize::normalize_email;
///
/// assert_eq!(normalize_email("Alice@EXAMPLE.COM"), "Alice@example.com");
/// ```
/// Applies all normalizations: Unicode NFC, whitespace trimming, and optional email normalization.
///
/// If `is_email` is `true`, also applies [`normalize_email`] to lowercase the domain.
///
/// # Examples
///
/// ```
/// use secure_boundary::normalize::normalize;
///
/// let result = normalize(" hello ", false);
/// assert_eq!(result, "hello");
///
/// let email = normalize(" User@EXAMPLE.COM ", true);
/// assert_eq!(email, "User@example.com");
/// ```