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 std::fmt::Display for Address {
175 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
176 write!(f, "0x")?;
177 for byte in &self.0 {
178 write!(f, "{byte:02x}")?;
179 }
180
181 Ok(())
182 }
183}
184
185impl std::fmt::Debug for Address {
186 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
187 f.debug_tuple("Address")
188 .field(&format_args!("\"{self}\""))
189 .finish()
190 }
191}
192
193#[cfg(feature = "serde")]
194#[cfg_attr(doc_cfg, doc(cfg(feature = "serde")))]
195struct ReadableAddress;
196
197#[cfg(feature = "serde")]
198#[cfg_attr(doc_cfg, doc(cfg(feature = "serde")))]
199impl serde_with::SerializeAs<[u8; Address::LENGTH]> for ReadableAddress {
200 fn serialize_as<S>(source: &[u8; Address::LENGTH], serializer: S) -> Result<S::Ok, S::Error>
201 where
202 S: serde::Serializer,
203 {
204 let address = Address::new(*source);
205 serde_with::DisplayFromStr::serialize_as(&address, serializer)
206 }
207}
208
209#[cfg(feature = "serde")]
210#[cfg_attr(doc_cfg, doc(cfg(feature = "serde")))]
211impl<'de> serde_with::DeserializeAs<'de, [u8; Address::LENGTH]> for ReadableAddress {
212 fn deserialize_as<D>(deserializer: D) -> Result<[u8; Address::LENGTH], D::Error>
213 where
214 D: serde::Deserializer<'de>,
215 {
216 let address: Address = serde_with::DisplayFromStr::deserialize_as(deserializer)?;
217 Ok(address.into_inner())
218 }
219}
220
221#[derive(Clone, Copy, Debug, PartialEq, Eq)]
222pub struct AddressParseError {
223 hex_error: Option<HexDecodeError>,
224}
225
226impl std::fmt::Display for AddressParseError {
227 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
228 write!(
229 f,
230 "Unable to parse Address (must be hex string of length {})",
231 Address::LENGTH
232 )
233 }
234}
235
236impl std::error::Error for AddressParseError {}
237
238#[allow(unused)]
239#[derive(Clone, Copy, Debug, PartialEq, Eq)]
240enum HexDecodeError {
241 EmptyInput,
242 InputTooLong(usize),
243 InvalidHexCharacter(u8),
244}
245
246impl HexDecodeError {
247 const fn const_panic(&self) -> ! {
248 match self {
249 HexDecodeError::EmptyInput => panic!("input hex string must be non-empty"),
250 HexDecodeError::InputTooLong(_) => panic!("input hex string is too long for address"),
251 HexDecodeError::InvalidHexCharacter(_) => {
252 panic!("input hex string has wrong character")
253 }
254 }
255 }
256}
257
258const fn hex_address_bytes(bytes: &[u8]) -> Result<[u8; Address::LENGTH], HexDecodeError> {
260 if bytes.is_empty() {
261 return Err(HexDecodeError::EmptyInput);
262 }
263 let hex = remove_0x_prefix(bytes);
264 if hex.len() > 64 {
265 return Err(HexDecodeError::InputTooLong(hex.len()));
266 }
267
268 let mut buffer = [0; Address::LENGTH];
270 let mut i = hex.len();
271 let mut j = buffer.len();
272 while i >= 2 {
273 let lo = HEX_DECODE_LUT[hex[i - 1] as usize];
274 let hi = HEX_DECODE_LUT[hex[i - 2] as usize];
275 if lo == NIL {
276 return Err(HexDecodeError::InvalidHexCharacter(hex[i - 1]));
277 }
278 if hi == NIL {
279 return Err(HexDecodeError::InvalidHexCharacter(hex[i - 2]));
280 }
281 buffer[j - 1] = (hi << 4) | lo;
282 i -= 2;
283 j -= 1;
284 }
285 if i == 1 {
286 let lo = HEX_DECODE_LUT[hex[0] as usize];
287 if lo == NIL {
288 return Err(HexDecodeError::InvalidHexCharacter(hex[0]));
289 }
290 buffer[j - 1] = lo;
291 }
292 Ok(buffer)
293}
294
295const fn remove_0x_prefix(hex: &[u8]) -> &[u8] {
297 if let Some((two, hex2)) = hex.split_first_chunk::<2>() {
298 if two[0] == b'0' && two[1] == b'x' {
299 return hex2;
300 }
301 }
302 hex
303}
304
305const HEX_DECODE_LUT: &[u8; 256] = &make_decode_lut();
309
310const NIL: u8 = u8::MAX;
312
313const fn make_decode_lut() -> [u8; 256] {
314 let mut lut = [0; 256];
315 let mut i = 0u8;
316 loop {
317 lut[i as usize] = match i {
318 b'0'..=b'9' => i - b'0',
319 b'A'..=b'F' => i - b'A' + 10,
320 b'a'..=b'f' => i - b'a' + 10,
321 _ => NIL,
323 };
324 if i == NIL {
325 break;
326 }
327 i += 1;
328 }
329 lut
330}
331
332#[cfg(test)]
333mod test {
334 use super::*;
335 use test_strategy::proptest;
336
337 #[cfg(target_arch = "wasm32")]
338 use wasm_bindgen_test::wasm_bindgen_test as test;
339
340 #[test]
341 fn hex_parsing() {
342 let actual = Address::from_hex("0x2").unwrap();
343 let expected = "0x0000000000000000000000000000000000000000000000000000000000000002";
344
345 assert_eq!(actual.to_string(), expected);
346 }
347
348 #[test]
349 #[cfg(feature = "serde")]
350 fn formats() {
351 let actual = Address::from_hex("0x2").unwrap();
352
353 println!("{}", serde_json::to_string(&actual).unwrap());
354 println!("{:?}", bcs::to_bytes(&actual).unwrap());
355 let a: Address = serde_json::from_str("\"0x2\"").unwrap();
356 println!("{a}");
357 }
358
359 #[proptest]
360 fn roundtrip_display_fromstr(address: Address) {
361 let s = address.to_string();
362 let a = s.parse::<Address>().unwrap();
363 assert_eq!(address, a);
364 }
365}