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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
//! Encoding traits for explicit secret-to-string conversion.
//!
//! > **Import paths:** `use secure_gate::ToHex;` etc. (not `secure_gate::traits::encoding::hex::ToHex`)
//!
//! All encoding traits require `alloc`. Every encoder returns
//! [`EncodedSecret`](crate::EncodedSecret): the encoded form is a second full copy of
//! the secret, and it stays wiped until it drops.
//! See the [`decoding`](super::decoding) module for the reverse direction.
//!
//! Each encoding trait has its own feature gate:
//!
//! | Trait | Feature |
//! |------------------|---------------------|
//! | [`ToHex`] | `encoding-hex` |
//! | [`ToBase32`] | `encoding-base32` |
//! | [`ToBase64Url`] | `encoding-base64` |
//! | [`ToBech32`] | `encoding-bech32` |
//! | [`ToBech32m`] | `encoding-bech32` |
/// Which case an encoder should emit.
///
/// This parameter appears only on encoders where both cases are canonical and decoding
/// accepts either — currently bech32 and bech32m, where BIP-173 forbids mixed case and
/// accepts either pure case, with the checksum defined over the lowercase form.
///
/// It is deliberately absent elsewhere, and the absence is the safety property:
///
/// - `to_base64url` takes no case, because base64url's alphabet gives `a`–`z` and
/// `A`–`Z` distinct meanings. Converting the case of a base64url string destroys it.
/// - `to_base32` takes no case, because RFC 4648 §6 output is uppercase by definition
/// and the decoder rejects anything else.
/// - `to_hex` / `to_hex_upper` stay two methods, because hex decoding is case-insensitive
/// either way and the pair predates this type.
///
/// A caller therefore cannot ask for a case conversion that would corrupt the value —
/// there is no parameter to pass.
/// Marker for types that may be **encoded**: byte-shaped sources.
///
/// *Available whenever any encoding feature is on (`encoding-hex`, `encoding-base32`,
/// `encoding-base64`, or `encoding-bech32`).*
///
/// Every encoding trait in this module is blanket-implemented for
/// `T: AsRef<[u8]> + EncodableBytes`. The second bound is what keeps string-shaped
/// types out, and it is load-bearing rather than decorative — removing it changes
/// which calls compile.
///
/// # Why the extra bound exists
///
/// `str` and `String` implement `AsRef<[u8]>`, so an `AsRef<[u8]>`-only blanket made
/// every string an encoding *input* — even though strings are this crate's decoding
/// input. Two silent wrong answers followed from that:
///
/// - `encoded.to_hex()` compiled for an [`EncodedSecret`](crate::EncodedSecret), which
/// derefs to `str`. It hex-encoded the *encoded text*: a 32-byte key came back as 124
/// hex characters, with no signature or name to suggest anything was wrong.
/// - `"text".to_hex()` encoded a string's UTF-8 bytes, which is occasionally what
/// someone means and usually not.
///
/// Both are now compile errors. Write `.as_bytes()` when you did mean the UTF-8.
///
/// # Implementing it
///
/// Implemented here for `[u8]`, `[u8; N]` and `Vec<u8>`. It is an **opt-in marker** in
/// the same family as [`CloneableSecret`](crate::CloneableSecret) and
/// [`SerializableSecret`](crate::SerializableSecret): implement it for your own
/// byte-shaped newtype to make it encodable.
///
/// ```rust
/// # #[cfg(all(feature = "encoding-hex", feature = "alloc"))] {
/// use secure_gate::{EncodableBytes, ToHex};
///
/// struct Nonce([u8; 12]);
/// impl AsRef<[u8]> for Nonce {
/// fn as_ref(&self) -> &[u8] { &self.0 }
/// }
/// impl EncodableBytes for Nonce {}
///
/// assert_eq!(Nonce([0xAB; 12]).to_hex().len(), 24);
/// # }
/// ```
///
/// The orphan rule means no downstream crate can implement it for `str` or `String`,
/// so the hole cannot be reopened from outside.
// Every encoding trait produces EncodedSecret — all require alloc
pub use ToBase32;
pub use ToBase64Url;
pub use ToBech32;
pub use ;
pub use ToBech32m;
pub use ;
pub use ToHex;