move_core_types/
account_address.rs1use hex::FromHex;
5use rand::{rngs::OsRng, Rng};
6use serde::{de::Error as _, Deserialize, Deserializer, Serialize, Serializer};
7use std::{convert::TryFrom, fmt, str::FromStr};
8
9#[derive(Ord, PartialOrd, Eq, PartialEq, Hash, Clone, Copy)]
11#[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))]
12pub struct AccountAddress([u8; AccountAddress::LENGTH]);
13
14impl AccountAddress {
15 pub const fn new(address: [u8; Self::LENGTH]) -> Self {
16 Self(address)
17 }
18
19 pub const LENGTH: usize = 16;
21
22 pub const ZERO: Self = Self([0u8; Self::LENGTH]);
24
25 pub fn random() -> Self {
26 let mut rng = OsRng;
27 let buf: [u8; Self::LENGTH] = rng.gen();
28 Self(buf)
29 }
30
31 pub fn short_str_lossless(&self) -> String {
32 let hex_str = hex::encode(&self.0).trim_start_matches('0').to_string();
33 if hex_str.is_empty() {
34 "0".to_string()
35 } else {
36 hex_str
37 }
38 }
39
40 pub fn to_vec(&self) -> Vec<u8> {
41 self.0.to_vec()
42 }
43
44 pub fn into_bytes(self) -> [u8; Self::LENGTH] {
45 self.0
46 }
47
48 pub fn from_hex_literal(literal: &str) -> Result<Self, AccountAddressParseError> {
49 if !literal.starts_with("0x") {
50 return Err(AccountAddressParseError);
51 }
52
53 let hex_len = literal.len() - 2;
54
55 if hex_len < Self::LENGTH * 2 {
57 let mut hex_str = String::with_capacity(Self::LENGTH * 2);
58 for _ in 0..Self::LENGTH * 2 - hex_len {
59 hex_str.push('0');
60 }
61 hex_str.push_str(&literal[2..]);
62 AccountAddress::from_hex(hex_str)
63 } else {
64 AccountAddress::from_hex(&literal[2..])
65 }
66 }
67
68 pub fn to_hex_literal(&self) -> String {
69 format!("0x{}", self.short_str_lossless())
70 }
71
72 pub fn from_hex<T: AsRef<[u8]>>(hex: T) -> Result<Self, AccountAddressParseError> {
73 <[u8; Self::LENGTH]>::from_hex(hex)
74 .map_err(|_| AccountAddressParseError)
75 .map(Self)
76 }
77
78 pub fn to_hex(&self) -> String {
79 format!("{:x}", self)
80 }
81
82 pub fn from_bytes<T: AsRef<[u8]>>(bytes: T) -> Result<Self, AccountAddressParseError> {
83 <[u8; Self::LENGTH]>::try_from(bytes.as_ref())
84 .map_err(|_| AccountAddressParseError)
85 .map(Self)
86 }
87}
88
89impl AsRef<[u8]> for AccountAddress {
90 fn as_ref(&self) -> &[u8] {
91 &self.0
92 }
93}
94
95impl std::ops::Deref for AccountAddress {
96 type Target = [u8; Self::LENGTH];
97
98 fn deref(&self) -> &Self::Target {
99 &self.0
100 }
101}
102
103impl fmt::Display for AccountAddress {
104 fn fmt(&self, f: &mut fmt::Formatter) -> std::fmt::Result {
105 write!(f, "{:X}", self)
106 }
107}
108
109impl fmt::Debug for AccountAddress {
110 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
111 write!(f, "{:X}", self)
112 }
113}
114
115impl fmt::LowerHex for AccountAddress {
116 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
117 if f.alternate() {
118 write!(f, "0x")?;
119 }
120
121 for byte in &self.0 {
122 write!(f, "{:02x}", byte)?;
123 }
124
125 Ok(())
126 }
127}
128
129impl fmt::UpperHex for AccountAddress {
130 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
131 if f.alternate() {
132 write!(f, "0x")?;
133 }
134
135 for byte in &self.0 {
136 write!(f, "{:02X}", byte)?;
137 }
138
139 Ok(())
140 }
141}
142
143impl From<[u8; AccountAddress::LENGTH]> for AccountAddress {
144 fn from(bytes: [u8; AccountAddress::LENGTH]) -> Self {
145 Self::new(bytes)
146 }
147}
148
149impl TryFrom<&[u8]> for AccountAddress {
150 type Error = AccountAddressParseError;
151
152 fn try_from(bytes: &[u8]) -> Result<AccountAddress, AccountAddressParseError> {
154 Self::from_bytes(bytes)
155 }
156}
157
158impl TryFrom<Vec<u8>> for AccountAddress {
159 type Error = AccountAddressParseError;
160
161 fn try_from(bytes: Vec<u8>) -> Result<AccountAddress, AccountAddressParseError> {
163 Self::from_bytes(bytes)
164 }
165}
166
167impl From<AccountAddress> for Vec<u8> {
168 fn from(addr: AccountAddress) -> Vec<u8> {
169 addr.0.to_vec()
170 }
171}
172
173impl From<&AccountAddress> for Vec<u8> {
174 fn from(addr: &AccountAddress) -> Vec<u8> {
175 addr.0.to_vec()
176 }
177}
178
179impl From<AccountAddress> for [u8; AccountAddress::LENGTH] {
180 fn from(addr: AccountAddress) -> Self {
181 addr.0
182 }
183}
184
185impl From<&AccountAddress> for [u8; AccountAddress::LENGTH] {
186 fn from(addr: &AccountAddress) -> Self {
187 addr.0
188 }
189}
190
191impl From<&AccountAddress> for String {
192 fn from(addr: &AccountAddress) -> String {
193 ::hex::encode(addr.as_ref())
194 }
195}
196
197impl TryFrom<String> for AccountAddress {
198 type Error = AccountAddressParseError;
199
200 fn try_from(s: String) -> Result<AccountAddress, AccountAddressParseError> {
201 Self::from_hex(s)
202 }
203}
204
205impl FromStr for AccountAddress {
206 type Err = AccountAddressParseError;
207
208 fn from_str(s: &str) -> Result<Self, AccountAddressParseError> {
209 Self::from_hex(s)
210 }
211}
212
213impl<'de> Deserialize<'de> for AccountAddress {
214 fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
215 where
216 D: Deserializer<'de>,
217 {
218 if deserializer.is_human_readable() {
219 let s = <String>::deserialize(deserializer)?;
220 AccountAddress::from_hex(s).map_err(D::Error::custom)
221 } else {
222 #[derive(::serde::Deserialize)]
226 #[serde(rename = "AccountAddress")]
227 struct Value([u8; AccountAddress::LENGTH]);
228
229 let value = Value::deserialize(deserializer)?;
230 Ok(AccountAddress::new(value.0))
231 }
232 }
233}
234
235impl Serialize for AccountAddress {
236 fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
237 where
238 S: Serializer,
239 {
240 if serializer.is_human_readable() {
241 self.to_hex().serialize(serializer)
242 } else {
243 serializer.serialize_newtype_struct("AccountAddress", &self.0)
245 }
246 }
247}
248
249#[derive(Clone, Copy, Debug)]
250pub struct AccountAddressParseError;
251
252impl fmt::Display for AccountAddressParseError {
253 fn fmt(&self, f: &mut fmt::Formatter) -> std::fmt::Result {
254 write!(f, "unable to parse AccoutAddress")
255 }
256}
257
258impl std::error::Error for AccountAddressParseError {}
259
260#[cfg(test)]
261mod tests {
262 use super::AccountAddress;
263 use hex::FromHex;
264 use proptest::prelude::*;
265 use std::{
266 convert::{AsRef, TryFrom},
267 str::FromStr,
268 };
269
270 #[test]
271 fn test_display_impls() {
272 let hex = "ca843279e3427144cead5e4d5999a3d0";
273 let upper_hex = "CA843279E3427144CEAD5E4D5999A3D0";
274
275 let address = AccountAddress::from_hex(hex).unwrap();
276
277 assert_eq!(format!("{}", address), upper_hex);
278 assert_eq!(format!("{:?}", address), upper_hex);
279 assert_eq!(format!("{:X}", address), upper_hex);
280 assert_eq!(format!("{:x}", address), hex);
281
282 assert_eq!(format!("{:#x}", address), format!("0x{}", hex));
283 assert_eq!(format!("{:#X}", address), format!("0x{}", upper_hex));
284 }
285
286 #[test]
287 fn test_short_str_lossless() {
288 let address = AccountAddress::from_hex("00c0f1f95c5b1c5f0eda533eff269000").unwrap();
289
290 assert_eq!(
291 address.short_str_lossless(),
292 "c0f1f95c5b1c5f0eda533eff269000",
293 );
294 }
295
296 #[test]
297 fn test_short_str_lossless_zero() {
298 let address = AccountAddress::from_hex("00000000000000000000000000000000").unwrap();
299
300 assert_eq!(address.short_str_lossless(), "0");
301 }
302
303 #[test]
304 fn test_address() {
305 let hex = "ca843279e3427144cead5e4d5999a3d0";
306 let bytes = Vec::from_hex(hex).expect("You must provide a valid Hex format");
307
308 assert_eq!(
309 bytes.len(),
310 AccountAddress::LENGTH as usize,
311 "Address {:?} is not {}-bytes long. Addresses must be {} bytes",
312 bytes,
313 AccountAddress::LENGTH,
314 AccountAddress::LENGTH,
315 );
316
317 let address = AccountAddress::from_hex(hex).unwrap();
318
319 assert_eq!(address.as_ref().to_vec(), bytes);
320 }
321
322 #[test]
323 fn test_from_hex_literal() {
324 let hex_literal = "0x1";
325 let hex = "00000000000000000000000000000001";
326
327 let address_from_literal = AccountAddress::from_hex_literal(hex_literal).unwrap();
328 let address = AccountAddress::from_hex(hex).unwrap();
329
330 assert_eq!(address_from_literal, address);
331 assert_eq!(hex_literal, address.to_hex_literal());
332
333 AccountAddress::from_hex_literal(hex).unwrap_err();
335 AccountAddress::from_hex_literal("0x100000000000000000000000000000001").unwrap_err();
337 }
338
339 #[test]
340 fn test_ref() {
341 let address = AccountAddress::new([1u8; AccountAddress::LENGTH]);
342 let _: &[u8] = address.as_ref();
343 }
344
345 #[test]
346 fn test_address_from_proto_invalid_length() {
347 let bytes = vec![1; 123];
348 AccountAddress::from_bytes(bytes).unwrap_err();
349 }
350
351 #[test]
352 fn test_deserialize_from_json_value() {
353 let address = AccountAddress::random();
354 let json_value = serde_json::to_value(address).expect("serde_json::to_value fail.");
355 let address2: AccountAddress =
356 serde_json::from_value(json_value).expect("serde_json::from_value fail.");
357 assert_eq!(address, address2)
358 }
359
360 #[test]
361 fn test_serde_json() {
362 let hex = "ca843279e3427144cead5e4d5999a3d0";
363 let json_hex = "\"ca843279e3427144cead5e4d5999a3d0\"";
364
365 let address = AccountAddress::from_hex(hex).unwrap();
366
367 let json = serde_json::to_string(&address).unwrap();
368 let json_address: AccountAddress = serde_json::from_str(json_hex).unwrap();
369
370 assert_eq!(json, json_hex);
371 assert_eq!(address, json_address);
372 }
373
374 #[test]
375 fn test_address_from_empty_string() {
376 assert!(AccountAddress::try_from("".to_string()).is_err());
377 assert!(AccountAddress::from_str("").is_err());
378 }
379
380 proptest! {
381 #[test]
382 fn test_address_string_roundtrip(addr in any::<AccountAddress>()) {
383 let s = String::from(&addr);
384 let addr2 = AccountAddress::try_from(s).expect("roundtrip to string should work");
385 prop_assert_eq!(addr, addr2);
386 }
387
388 #[test]
389 fn test_address_protobuf_roundtrip(addr in any::<AccountAddress>()) {
390 let bytes = addr.to_vec();
391 prop_assert_eq!(bytes.clone(), addr.as_ref());
392 let addr2 = AccountAddress::try_from(&bytes[..]).unwrap();
393 prop_assert_eq!(addr, addr2);
394 }
395 }
396}