1use std::{fmt, str};
2
3use super::Key;
4use crate::finite::Empty;
5
6#[derive(Clone, Copy, Debug, Eq, PartialEq, thiserror::Error)]
7#[error("invalid base58")]
8pub struct Error;
9
10pub type Result<T, E = Error> = std::result::Result<T, E>;
11
12#[derive(Clone, Debug, DeserializeFromStr, Eq, Ord, PartialEq, PartialOrd, SerializeDisplay)]
13pub struct Base58 {
14 bytes: Vec<u8>,
15 string: String,
16}
17
18impl Empty for Key {
19 const EMPTY: Self = Key(0);
20
21 fn is_empty(&self) -> bool {
22 *self == Self::EMPTY
23 }
24}
25
26impl fmt::Display for Key {
27 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
28 Base58::encode(&self.0.to_be_bytes()).fmt(f)
29 }
30}
31
32impl str::FromStr for Key {
33 type Err = Error;
34
35 fn from_str(s: &str) -> Result<Self, Self::Err> {
36 let bytes = Base58::decode(s)?;
37 let bytes: [u8; 16] = bytes.try_into().map_err(|_| Error)?;
38 Ok(Self(u128::from_be_bytes(bytes)))
39 }
40}
41
42#[cfg(feature = "serde")]
43impl serde::Serialize for Key {
44 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
45 where
46 S: serde::Serializer,
47 {
48 if serializer.is_human_readable() {
49 serializer.serialize_str(&self.to_string())
50 } else {
51 serializer.serialize_bytes(&self.0.to_be_bytes())
52 }
53 }
54}
55
56#[cfg(feature = "serde")]
57impl<'de> serde::Deserialize<'de> for Key {
58 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
59 where
60 D: serde::Deserializer<'de>,
61 {
62 use serde::de::Visitor;
63
64 struct KeyVisitor;
65
66 impl<'de> Visitor<'de> for KeyVisitor {
67 type Value = Key;
68
69 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
70 formatter.write_str("a base58 string or 16 bytes")
71 }
72
73 fn visit_str<E>(self, value: &str) -> Result<Key, E>
74 where
75 E: serde::de::Error,
76 {
77 value.parse().map_err(E::custom)
78 }
79
80 fn visit_bytes<E>(self, value: &[u8]) -> Result<Key, E>
81 where
82 E: serde::de::Error,
83 {
84 let bytes: [u8; 16] = value.try_into().map_err(|_| E::custom("invalid key"))?;
85 Ok(Key(u128::from_be_bytes(bytes)))
86 }
87
88 fn visit_seq<A>(self, mut seq: A) -> Result<Key, A::Error>
89 where
90 A: serde::de::SeqAccess<'de>,
91 {
92 let mut bytes = [0u8; 16];
93 for (index, byte) in bytes.iter_mut().enumerate() {
94 *byte = seq
95 .next_element()?
96 .ok_or_else(|| serde::de::Error::invalid_length(index, &self))?;
97 }
98 if seq.next_element::<u8>()?.is_some() {
99 return Err(serde::de::Error::invalid_length(17, &self));
100 }
101 Ok(Key(u128::from_be_bytes(bytes)))
102 }
103 }
104
105 if deserializer.is_human_readable() {
106 deserializer.deserialize_str(KeyVisitor)
107 } else {
108 deserializer.deserialize_bytes(KeyVisitor)
109 }
110 }
111}
112
113impl Base58 {
114 pub const LETTERS: [u8; 58] = *b"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
115
116 pub const OCTETS: [u8; 128] = {
117 let mut octets = [0xff; 128];
118 let mut index = 0;
119 while index < Self::LETTERS.len() {
120 octets[Self::LETTERS[index] as usize] = index as u8;
121 index += 1;
122 }
123 octets
124 };
125
126 pub fn new(bytes: &[u8]) -> Self {
127 Self { bytes: bytes.to_vec(), string: Self::encode(bytes) }
128 }
129
130 pub fn parse(s: &str) -> Result<Self> {
131 s.parse()
132 }
133
134 pub fn random_bytes(len: usize) -> Self {
135 use rand::RngExt as _;
136
137 let mut vec = vec![0u8; len];
138 rand::rng().fill(vec.as_mut_slice());
139 Self::new(&vec)
140 }
141
142 pub fn random_str(len: usize) -> Self {
143 use rand::RngExt as _;
144
145 let mut rng = rand::rng();
146 let string = (0..len)
147 .map(|_| Self::LETTERS[rng.random_range(0..Self::LETTERS.len())])
148 .collect::<Vec<_>>();
149 str::from_utf8(&string).unwrap().parse().unwrap()
150 }
151
152 pub fn encode(bytes: &[u8]) -> String {
153 let zeros = bytes.iter().take_while(|&&byte| byte == 0).count();
154 let mut digits = Vec::<u8>::new();
155 for &byte in bytes {
156 let mut carry = byte as u32;
157 for digit in &mut digits {
158 carry += (*digit as u32) << 8;
159 *digit = (carry % 58) as u8;
160 carry /= 58;
161 }
162 while carry > 0 {
163 digits.push((carry % 58) as u8);
164 carry /= 58;
165 }
166 }
167
168 let mut string = String::with_capacity(zeros + digits.len());
169 string.extend(core::iter::repeat_n('1', zeros));
170 string.extend(digits.iter().rev().map(|digit| Self::LETTERS[*digit as usize] as char));
171 string
172 }
173
174 pub fn decode(s: &str) -> Result<Vec<u8>> {
175 let zeros = s.bytes().take_while(|&byte| byte == b'1').count();
176 let mut bytes = Vec::<u8>::new();
177 for byte in s.bytes() {
178 if byte as usize >= Self::OCTETS.len() {
179 return Err(Error);
180 }
181 let digit = Self::OCTETS[byte as usize];
182 if digit == 0xff {
183 return Err(Error);
184 }
185 let mut carry = digit as u32;
186 for decoded in &mut bytes {
187 carry += (*decoded as u32) * 58;
188 *decoded = (carry & 0xff) as u8;
189 carry >>= 8;
190 }
191 while carry > 0 {
192 bytes.push((carry & 0xff) as u8);
193 carry >>= 8;
194 }
195 }
196
197 let mut decoded = vec![0; zeros];
198 decoded.extend(bytes.iter().rev());
199 Ok(decoded)
200 }
201
202 pub const fn as_bytes(&self) -> &[u8] {
203 self.bytes.as_slice()
204 }
205
206 pub const fn as_str(&self) -> &str {
207 self.string.as_str()
208 }
209}
210
211impl str::FromStr for Base58 {
212 type Err = Error;
213
214 fn from_str(s: &str) -> Result<Self> {
215 Ok(Self { bytes: Self::decode(s)?, string: s.to_string() })
216 }
217}
218
219impl fmt::Display for Base58 {
220 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
221 self.string.fmt(f)
222 }
223}
224
225impl From<Base58> for String {
226 fn from(base58: Base58) -> Self {
227 base58.string
228 }
229}
230
231#[cfg(test)]
232mod tests {
233 use super::{Base58, Key};
234
235 #[test]
236 fn key_display_roundtrip() {
237 for key in [Key(0), Key(1), Key(u128::MAX), Key(0x0123_4567_89ab_cdef_fedc_ba98_7654_3210)]
238 {
239 assert_eq!(key.to_string().parse::<Key>().unwrap(), key);
240 }
241 }
242
243 #[cfg(feature = "serde")]
244 #[test]
245 fn json_serialize_key_as_base58_string() {
246 let key = Key(0x0123_4567_89ab_cdef_fedc_ba98_7654_3210);
247 let json = serde_json::to_string(&key).unwrap();
248 assert!(json.starts_with('"'));
249 assert_eq!(serde_json::from_str::<Key>(&json).unwrap(), key);
250 }
251
252 #[test]
253 fn known_vectors() {
254 let vectors: &[(&[u8], &str)] = &[
255 (&[], ""),
256 (&[0], "1"),
257 (&[0, 0, 0, 1], "1112"),
258 (&[0x61], "2g"),
259 (&[0x62, 0x62, 0x62], "a3gV"),
260 (&[0x63, 0x63, 0x63], "aPEr"),
261 (
262 &[
263 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x79, 0x20, 0x61, 0x20, 0x6c, 0x6f, 0x6e, 0x67,
264 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67,
265 ],
266 "2cFupjhnEsSn59qHXstmK2ffpLv2",
267 ),
268 ];
269
270 for (bytes, encoded) in vectors {
271 assert_eq!(Base58::encode(bytes), *encoded);
272 assert_eq!(Base58::decode(encoded).unwrap(), *bytes);
273 let base58 = Base58::new(bytes);
274 assert_eq!(base58.as_str(), *encoded);
275 assert_eq!(base58.as_bytes(), *bytes);
276 }
277 }
278
279 #[test]
280 fn reject_invalid_characters() {
281 for invalid in ["0", "O", "I", "l", "+", "/", "abc0"] {
282 assert!(Base58::decode(invalid).is_err());
283 assert!(Base58::parse(invalid).is_err());
284 }
285 }
286}