1#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
52#[cfg_attr(
53 feature = "serde",
54 derive(serde_derive::Serialize, serde_derive::Deserialize)
55)]
56#[cfg_attr(feature = "proptest", derive(test_strategy::Arbitrary))]
57#[doc(alias = "ObjectId")]
58pub struct Address(
59 #[cfg_attr(
60 feature = "serde",
61 serde(with = "::serde_with::As::<::serde_with::IfIsHumanReadable<ReadableAddress>>")
62 )]
63 [u8; Self::LENGTH],
64);
65
66impl Address {
67 pub const LENGTH: usize = 32;
68 pub const ZERO: Self = Self([0u8; Self::LENGTH]);
69 pub const TWO: Self = Self::from_u8(2);
70 pub const THREE: Self = Self::from_u8(3);
71
72 pub const fn new(bytes: [u8; Self::LENGTH]) -> Self {
73 Self(bytes)
74 }
75
76 const fn from_u8(byte: u8) -> Self {
77 let mut address = Self::ZERO;
78 address.0[31] = byte;
79 address
80 }
81
82 #[cfg(feature = "rand")]
83 #[cfg_attr(doc_cfg, doc(cfg(feature = "rand")))]
84 pub fn generate<R>(mut rng: R) -> Self
85 where
86 R: rand_core::RngCore + rand_core::CryptoRng,
87 {
88 let mut buf: [u8; Self::LENGTH] = [0; Self::LENGTH];
89 rng.fill_bytes(&mut buf);
90 Self::new(buf)
91 }
92
93 pub const fn into_inner(self) -> [u8; Self::LENGTH] {
95 self.0
96 }
97
98 pub const fn inner(&self) -> &[u8; Self::LENGTH] {
99 &self.0
100 }
101
102 pub const fn as_bytes(&self) -> &[u8] {
103 &self.0
104 }
105
106 pub fn from_hex<T: AsRef<[u8]>>(hex: T) -> Result<Self, AddressParseError> {
108 let hex = hex.as_ref();
109
110 hex_address_bytes(hex)
111 .map(Self)
112 .map_err(|e| AddressParseError { hex_error: Some(e) })
113 }
114
115 pub const fn from_hex_unwrap(hex: &str) -> Self {
119 match hex_address_bytes(hex.as_bytes()) {
120 Ok(address) => Self(address),
121 Err(e) => e.const_panic(),
122 }
123 }
124
125 pub fn to_hex(&self) -> String {
126 self.to_string()
127 }
128
129 pub fn from_bytes<T: AsRef<[u8]>>(bytes: T) -> Result<Self, AddressParseError> {
130 <[u8; Self::LENGTH]>::try_from(bytes.as_ref())
131 .map_err(|_| AddressParseError { hex_error: None })
132 .map(Self)
133 }
134}
135
136impl std::str::FromStr for Address {
137 type Err = AddressParseError;
138
139 fn from_str(s: &str) -> Result<Self, Self::Err> {
140 Self::from_hex(s)
141 }
142}
143
144impl AsRef<[u8]> for Address {
145 fn as_ref(&self) -> &[u8] {
146 &self.0
147 }
148}
149
150impl AsRef<[u8; 32]> for Address {
151 fn as_ref(&self) -> &[u8; 32] {
152 &self.0
153 }
154}
155
156impl From<Address> for [u8; 32] {
157 fn from(address: Address) -> Self {
158 address.into_inner()
159 }
160}
161
162impl From<[u8; 32]> for Address {
163 fn from(address: [u8; 32]) -> Self {
164 Self::new(address)
165 }
166}
167
168impl From<Address> for Vec<u8> {
169 fn from(value: Address) -> Self {
170 value.0.to_vec()
171 }
172}
173
174impl From<&Address> for Vec<u8> {
175 fn from(value: &Address) -> Self {
176 value.0.to_vec()
177 }
178}
179
180impl From<Address> for String {
181 fn from(value: Address) -> Self {
182 value.to_string()
183 }
184}
185
186impl From<&Address> for String {
187 fn from(value: &Address) -> Self {
188 value.to_string()
189 }
190}
191
192impl std::fmt::Display for Address {
193 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
194 write!(f, "0x")?;
195 for byte in &self.0 {
196 write!(f, "{byte:02x}")?;
197 }
198
199 Ok(())
200 }
201}
202
203impl std::fmt::Debug for Address {
204 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
205 f.debug_tuple("Address")
206 .field(&format_args!("\"{self}\""))
207 .finish()
208 }
209}
210
211#[cfg(feature = "serde")]
212#[cfg_attr(doc_cfg, doc(cfg(feature = "serde")))]
213struct ReadableAddress;
214
215#[cfg(feature = "serde")]
216#[cfg_attr(doc_cfg, doc(cfg(feature = "serde")))]
217impl serde_with::SerializeAs<[u8; Address::LENGTH]> for ReadableAddress {
218 fn serialize_as<S>(source: &[u8; Address::LENGTH], serializer: S) -> Result<S::Ok, S::Error>
219 where
220 S: serde::Serializer,
221 {
222 let address = Address::new(*source);
223 serde_with::DisplayFromStr::serialize_as(&address, serializer)
224 }
225}
226
227#[cfg(feature = "serde")]
228#[cfg_attr(doc_cfg, doc(cfg(feature = "serde")))]
229impl<'de> serde_with::DeserializeAs<'de, [u8; Address::LENGTH]> for ReadableAddress {
230 fn deserialize_as<D>(deserializer: D) -> Result<[u8; Address::LENGTH], D::Error>
231 where
232 D: serde::Deserializer<'de>,
233 {
234 let address: Address = serde_with::DisplayFromStr::deserialize_as(deserializer)?;
235 Ok(address.into_inner())
236 }
237}
238
239#[derive(Clone, Copy, Debug, PartialEq, Eq)]
240pub struct AddressParseError {
241 hex_error: Option<HexDecodeError>,
242}
243
244impl std::fmt::Display for AddressParseError {
245 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
246 write!(
247 f,
248 "Unable to parse Address (must be hex string of length {})",
249 Address::LENGTH
250 )
251 }
252}
253
254impl std::error::Error for AddressParseError {}
255
256#[allow(unused)]
257#[derive(Clone, Copy, Debug, PartialEq, Eq)]
258enum HexDecodeError {
259 EmptyInput,
260 InputTooLong(usize),
261 InvalidHexCharacter(u8),
262}
263
264impl HexDecodeError {
265 const fn const_panic(&self) -> ! {
266 match self {
267 HexDecodeError::EmptyInput => panic!("input hex string must be non-empty"),
268 HexDecodeError::InputTooLong(_) => panic!("input hex string is too long for address"),
269 HexDecodeError::InvalidHexCharacter(_) => {
270 panic!("input hex string has wrong character")
271 }
272 }
273 }
274}
275
276const fn hex_address_bytes(bytes: &[u8]) -> Result<[u8; Address::LENGTH], HexDecodeError> {
278 if bytes.is_empty() {
279 return Err(HexDecodeError::EmptyInput);
280 }
281 let hex = remove_0x_prefix(bytes);
282 if hex.len() > 64 {
283 return Err(HexDecodeError::InputTooLong(hex.len()));
284 }
285
286 let mut buffer = [0; Address::LENGTH];
288 let mut i = hex.len();
289 let mut j = buffer.len();
290 while i >= 2 {
291 let lo = HEX_DECODE_LUT[hex[i - 1] as usize];
292 let hi = HEX_DECODE_LUT[hex[i - 2] as usize];
293 if lo == NIL {
294 return Err(HexDecodeError::InvalidHexCharacter(hex[i - 1]));
295 }
296 if hi == NIL {
297 return Err(HexDecodeError::InvalidHexCharacter(hex[i - 2]));
298 }
299 buffer[j - 1] = (hi << 4) | lo;
300 i -= 2;
301 j -= 1;
302 }
303 if i == 1 {
304 let lo = HEX_DECODE_LUT[hex[0] as usize];
305 if lo == NIL {
306 return Err(HexDecodeError::InvalidHexCharacter(hex[0]));
307 }
308 buffer[j - 1] = lo;
309 }
310 Ok(buffer)
311}
312
313const fn remove_0x_prefix(hex: &[u8]) -> &[u8] {
315 if let Some((two, hex2)) = hex.split_first_chunk::<2>() {
316 if two[0] == b'0' && two[1] == b'x' {
317 return hex2;
318 }
319 }
320 hex
321}
322
323const HEX_DECODE_LUT: &[u8; 256] = &make_decode_lut();
327
328const NIL: u8 = u8::MAX;
330
331const fn make_decode_lut() -> [u8; 256] {
332 let mut lut = [0; 256];
333 let mut i = 0u8;
334 loop {
335 lut[i as usize] = match i {
336 b'0'..=b'9' => i - b'0',
337 b'A'..=b'F' => i - b'A' + 10,
338 b'a'..=b'f' => i - b'a' + 10,
339 _ => NIL,
341 };
342 if i == NIL {
343 break;
344 }
345 i += 1;
346 }
347 lut
348}
349
350#[cfg(test)]
351mod test {
352 use super::*;
353 use test_strategy::proptest;
354
355 #[cfg(target_arch = "wasm32")]
356 use wasm_bindgen_test::wasm_bindgen_test as test;
357
358 #[test]
359 fn hex_parsing() {
360 let actual = Address::from_hex("0x2").unwrap();
361 let expected = "0x0000000000000000000000000000000000000000000000000000000000000002";
362
363 assert_eq!(actual.to_string(), expected);
364 }
365
366 #[test]
367 #[cfg(feature = "serde")]
368 fn formats() {
369 let actual = Address::from_hex("0x2").unwrap();
370
371 println!("{}", serde_json::to_string(&actual).unwrap());
372 println!("{:?}", bcs::to_bytes(&actual).unwrap());
373 let a: Address = serde_json::from_str("\"0x2\"").unwrap();
374 println!("{a}");
375 }
376
377 #[proptest]
378 fn roundtrip_display_fromstr(address: Address) {
379 let s = address.to_string();
380 let a = s.parse::<Address>().unwrap();
381 assert_eq!(address, a);
382 }
383}