1#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
50#[cfg_attr(
51 feature = "serde",
52 derive(serde_derive::Serialize, serde_derive::Deserialize)
53)]
54#[cfg_attr(feature = "proptest", derive(test_strategy::Arbitrary))]
55pub struct Address(
56 #[cfg_attr(
57 feature = "serde",
58 serde(with = "::serde_with::As::<::serde_with::IfIsHumanReadable<ReadableAddress>>")
59 )]
60 [u8; Self::LENGTH],
61);
62
63impl Address {
64 pub const LENGTH: usize = 32;
65 pub const ZERO: Self = Self([0u8; Self::LENGTH]);
66 pub const TWO: Self = Self::from_u8(2);
67 pub const THREE: Self = Self::from_u8(3);
68
69 pub const fn new(bytes: [u8; Self::LENGTH]) -> Self {
70 Self(bytes)
71 }
72
73 const fn from_u8(byte: u8) -> Self {
74 let mut address = Self::ZERO;
75 address.0[31] = byte;
76 address
77 }
78
79 #[cfg(feature = "rand")]
80 #[cfg_attr(doc_cfg, doc(cfg(feature = "rand")))]
81 pub fn generate<R>(mut rng: R) -> Self
82 where
83 R: rand_core::RngCore + rand_core::CryptoRng,
84 {
85 let mut buf: [u8; Self::LENGTH] = [0; Self::LENGTH];
86 rng.fill_bytes(&mut buf);
87 Self::new(buf)
88 }
89
90 pub const fn into_inner(self) -> [u8; Self::LENGTH] {
92 self.0
93 }
94
95 pub const fn inner(&self) -> &[u8; Self::LENGTH] {
96 &self.0
97 }
98
99 pub const fn as_bytes(&self) -> &[u8] {
100 &self.0
101 }
102
103 pub fn from_hex<T: AsRef<[u8]>>(hex: T) -> Result<Self, AddressParseError> {
104 let hex = hex.as_ref();
105
106 if !hex.starts_with(b"0x") {
107 return Err(AddressParseError);
108 }
109
110 let hex = &hex[2..];
111
112 if hex.len() < Self::LENGTH * 2 {
114 let mut buf = [b'0'; Self::LENGTH * 2];
115 let pad_length = (Self::LENGTH * 2) - hex.len();
116
117 buf[pad_length..].copy_from_slice(hex);
118
119 <[u8; Self::LENGTH] as hex::FromHex>::from_hex(buf)
120 } else {
121 <[u8; Self::LENGTH] as hex::FromHex>::from_hex(hex)
122 }
123 .map(Self)
124 .map_err(|_| AddressParseError)
126 }
127
128 pub fn to_hex(&self) -> String {
129 self.to_string()
130 }
131
132 pub fn from_bytes<T: AsRef<[u8]>>(bytes: T) -> Result<Self, AddressParseError> {
133 <[u8; Self::LENGTH]>::try_from(bytes.as_ref())
134 .map_err(|_| AddressParseError)
135 .map(Self)
136 }
137}
138
139impl std::str::FromStr for Address {
140 type Err = AddressParseError;
141
142 fn from_str(s: &str) -> Result<Self, Self::Err> {
143 Self::from_hex(s)
144 }
145}
146
147impl AsRef<[u8]> for Address {
148 fn as_ref(&self) -> &[u8] {
149 &self.0
150 }
151}
152
153impl AsRef<[u8; 32]> for Address {
154 fn as_ref(&self) -> &[u8; 32] {
155 &self.0
156 }
157}
158
159impl From<Address> for [u8; 32] {
160 fn from(address: Address) -> Self {
161 address.into_inner()
162 }
163}
164
165impl From<[u8; 32]> for Address {
166 fn from(address: [u8; 32]) -> Self {
167 Self::new(address)
168 }
169}
170
171impl From<Address> for Vec<u8> {
172 fn from(value: Address) -> Self {
173 value.0.to_vec()
174 }
175}
176
177impl From<super::ObjectId> for Address {
178 fn from(value: super::ObjectId) -> Self {
179 Self::new(value.into_inner())
180 }
181}
182
183impl std::fmt::Display for Address {
184 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
185 write!(f, "0x")?;
186 for byte in &self.0 {
187 write!(f, "{:02x}", byte)?;
188 }
189
190 Ok(())
191 }
192}
193
194impl std::fmt::Debug for Address {
195 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
196 f.debug_tuple("Address")
197 .field(&format_args!("\"{}\"", self))
198 .finish()
199 }
200}
201
202#[cfg(feature = "serde")]
203#[cfg_attr(doc_cfg, doc(cfg(feature = "serde")))]
204struct ReadableAddress;
205
206#[cfg(feature = "serde")]
207#[cfg_attr(doc_cfg, doc(cfg(feature = "serde")))]
208impl serde_with::SerializeAs<[u8; Address::LENGTH]> for ReadableAddress {
209 fn serialize_as<S>(source: &[u8; Address::LENGTH], serializer: S) -> Result<S::Ok, S::Error>
210 where
211 S: serde::Serializer,
212 {
213 let address = Address::new(*source);
214 serde_with::DisplayFromStr::serialize_as(&address, serializer)
215 }
216}
217
218#[cfg(feature = "serde")]
219#[cfg_attr(doc_cfg, doc(cfg(feature = "serde")))]
220impl<'de> serde_with::DeserializeAs<'de, [u8; Address::LENGTH]> for ReadableAddress {
221 fn deserialize_as<D>(deserializer: D) -> Result<[u8; Address::LENGTH], D::Error>
222 where
223 D: serde::Deserializer<'de>,
224 {
225 let address: Address = serde_with::DisplayFromStr::deserialize_as(deserializer)?;
226 Ok(address.into_inner())
227 }
228}
229
230#[derive(Clone, Copy, Debug, PartialEq, Eq)]
231pub struct AddressParseError;
232
233impl std::fmt::Display for AddressParseError {
234 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
235 write!(
236 f,
237 "Unable to parse Address (must be hex string of length {})",
238 Address::LENGTH
239 )
240 }
241}
242
243impl std::error::Error for AddressParseError {}
244
245#[cfg(test)]
246mod test {
247 use super::*;
248 use test_strategy::proptest;
249
250 #[cfg(target_arch = "wasm32")]
251 use wasm_bindgen_test::wasm_bindgen_test as test;
252
253 #[test]
254 fn hex_parsing() {
255 let actual = Address::from_hex("0x2").unwrap();
256 let expected = "0x0000000000000000000000000000000000000000000000000000000000000002";
257
258 assert_eq!(actual.to_string(), expected);
259 }
260
261 #[test]
262 #[cfg(feature = "serde")]
263 fn formats() {
264 let actual = Address::from_hex("0x2").unwrap();
265
266 println!("{}", serde_json::to_string(&actual).unwrap());
267 println!("{:?}", bcs::to_bytes(&actual).unwrap());
268 let a: Address = serde_json::from_str("\"0x2\"").unwrap();
269 println!("{a}");
270 }
271
272 #[proptest]
273 fn roundtrip_display_fromstr(address: Address) {
274 let s = address.to_string();
275 let a = s.parse::<Address>().unwrap();
276 assert_eq!(address, a);
277 }
278}