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> {
107 let hex = hex.as_ref();
108
109 if !hex.starts_with(b"0x") {
110 return Err(AddressParseError);
111 }
112
113 let hex = &hex[2..];
114
115 if hex.len() < Self::LENGTH * 2 {
117 let mut buf = [b'0'; Self::LENGTH * 2];
118 let pad_length = (Self::LENGTH * 2) - hex.len();
119
120 buf[pad_length..].copy_from_slice(hex);
121
122 <[u8; Self::LENGTH] as hex::FromHex>::from_hex(buf)
123 } else {
124 <[u8; Self::LENGTH] as hex::FromHex>::from_hex(hex)
125 }
126 .map(Self)
127 .map_err(|_| AddressParseError)
129 }
130
131 pub fn to_hex(&self) -> String {
132 self.to_string()
133 }
134
135 pub fn from_bytes<T: AsRef<[u8]>>(bytes: T) -> Result<Self, AddressParseError> {
136 <[u8; Self::LENGTH]>::try_from(bytes.as_ref())
137 .map_err(|_| AddressParseError)
138 .map(Self)
139 }
140}
141
142impl std::str::FromStr for Address {
143 type Err = AddressParseError;
144
145 fn from_str(s: &str) -> Result<Self, Self::Err> {
146 Self::from_hex(s)
147 }
148}
149
150impl AsRef<[u8]> for Address {
151 fn as_ref(&self) -> &[u8] {
152 &self.0
153 }
154}
155
156impl AsRef<[u8; 32]> for Address {
157 fn as_ref(&self) -> &[u8; 32] {
158 &self.0
159 }
160}
161
162impl From<Address> for [u8; 32] {
163 fn from(address: Address) -> Self {
164 address.into_inner()
165 }
166}
167
168impl From<[u8; 32]> for Address {
169 fn from(address: [u8; 32]) -> Self {
170 Self::new(address)
171 }
172}
173
174impl From<Address> for Vec<u8> {
175 fn from(value: Address) -> Self {
176 value.0.to_vec()
177 }
178}
179
180impl std::fmt::Display for Address {
181 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
182 write!(f, "0x")?;
183 for byte in &self.0 {
184 write!(f, "{byte:02x}")?;
185 }
186
187 Ok(())
188 }
189}
190
191impl std::fmt::Debug for Address {
192 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
193 f.debug_tuple("Address")
194 .field(&format_args!("\"{self}\""))
195 .finish()
196 }
197}
198
199#[cfg(feature = "serde")]
200#[cfg_attr(doc_cfg, doc(cfg(feature = "serde")))]
201struct ReadableAddress;
202
203#[cfg(feature = "serde")]
204#[cfg_attr(doc_cfg, doc(cfg(feature = "serde")))]
205impl serde_with::SerializeAs<[u8; Address::LENGTH]> for ReadableAddress {
206 fn serialize_as<S>(source: &[u8; Address::LENGTH], serializer: S) -> Result<S::Ok, S::Error>
207 where
208 S: serde::Serializer,
209 {
210 let address = Address::new(*source);
211 serde_with::DisplayFromStr::serialize_as(&address, serializer)
212 }
213}
214
215#[cfg(feature = "serde")]
216#[cfg_attr(doc_cfg, doc(cfg(feature = "serde")))]
217impl<'de> serde_with::DeserializeAs<'de, [u8; Address::LENGTH]> for ReadableAddress {
218 fn deserialize_as<D>(deserializer: D) -> Result<[u8; Address::LENGTH], D::Error>
219 where
220 D: serde::Deserializer<'de>,
221 {
222 let address: Address = serde_with::DisplayFromStr::deserialize_as(deserializer)?;
223 Ok(address.into_inner())
224 }
225}
226
227#[derive(Clone, Copy, Debug, PartialEq, Eq)]
228pub struct AddressParseError;
229
230impl std::fmt::Display for AddressParseError {
231 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
232 write!(
233 f,
234 "Unable to parse Address (must be hex string of length {})",
235 Address::LENGTH
236 )
237 }
238}
239
240impl std::error::Error for AddressParseError {}
241
242#[cfg(test)]
243mod test {
244 use super::*;
245 use test_strategy::proptest;
246
247 #[cfg(target_arch = "wasm32")]
248 use wasm_bindgen_test::wasm_bindgen_test as test;
249
250 #[test]
251 fn hex_parsing() {
252 let actual = Address::from_hex("0x2").unwrap();
253 let expected = "0x0000000000000000000000000000000000000000000000000000000000000002";
254
255 assert_eq!(actual.to_string(), expected);
256 }
257
258 #[test]
259 #[cfg(feature = "serde")]
260 fn formats() {
261 let actual = Address::from_hex("0x2").unwrap();
262
263 println!("{}", serde_json::to_string(&actual).unwrap());
264 println!("{:?}", bcs::to_bytes(&actual).unwrap());
265 let a: Address = serde_json::from_str("\"0x2\"").unwrap();
266 println!("{a}");
267 }
268
269 #[proptest]
270 fn roundtrip_display_fromstr(address: Address) {
271 let s = address.to_string();
272 let a = s.parse::<Address>().unwrap();
273 assert_eq!(address, a);
274 }
275}