Skip to main content

outmove_common/types/
account_address.rs

1// Copyright (c) The Diem Core Contributors
2// SPDX-License-Identifier: Apache-2.0
3
4use anyhow::{ensure, Error, Result};
5use rand::{rngs::OsRng, Rng};
6use serde::{de::Error as _, Deserialize, Deserializer, Serialize, Serializer};
7use std::{convert::TryFrom, fmt, str::FromStr};
8
9/// A struct that represents an account address.
10#[derive(Ord, PartialOrd, Eq, PartialEq, Hash, Clone, Copy)]
11pub struct AccountAddress([u8; AccountAddress::LENGTH]);
12
13impl AccountAddress {
14    pub const fn new(address: [u8; Self::LENGTH]) -> Self {
15        Self(address)
16    }
17
18    /// The number of bytes in an address.
19    pub const LENGTH: usize = 16;
20
21    /// Hex address: 0x0
22    pub const ZERO: Self = Self([0u8; Self::LENGTH]);
23
24    pub fn random() -> Self {
25        let mut rng = OsRng;
26        let buf: [u8; Self::LENGTH] = rng.gen();
27        Self(buf)
28    }
29
30    pub fn short_str_lossless(&self) -> String {
31        let hex_str = hex::encode(&self.0).trim_start_matches('0').to_string();
32        if hex_str.is_empty() {
33            "0".to_string()
34        } else {
35            hex_str
36        }
37    }
38
39    pub fn to_vec(&self) -> Vec<u8> {
40        self.0.to_vec()
41    }
42
43    pub fn to_u8(self) -> [u8; Self::LENGTH] {
44        self.0
45    }
46
47    pub fn from_hex_literal(literal: &str) -> Result<Self> {
48        ensure!(literal.starts_with("0x"), "literal must start with 0x.");
49
50        let hex_len = literal.len() - 2;
51        let mut result = if hex_len % 2 != 0 {
52            let mut hex_str = String::with_capacity(hex_len + 1);
53            hex_str.push('0');
54            hex_str.push_str(&literal[2..]);
55            hex::decode(&hex_str)?
56        } else {
57            hex::decode(&literal[2..])?
58        };
59
60        let len = result.len();
61        let padded_result = if len < Self::LENGTH {
62            let mut padded = Vec::with_capacity(Self::LENGTH);
63            padded.resize(Self::LENGTH - len, 0u8);
64            padded.append(&mut result);
65            padded
66        } else {
67            result
68        };
69
70        AccountAddress::try_from(padded_result)
71    }
72}
73
74impl AsRef<[u8]> for AccountAddress {
75    fn as_ref(&self) -> &[u8] {
76        &self.0
77    }
78}
79
80impl fmt::Display for AccountAddress {
81    fn fmt(&self, f: &mut fmt::Formatter) -> std::fmt::Result {
82        // Forward to the UpperHex impl with a "0x" prepended (the # flag).
83        write!(f, "{:#X}", self)
84    }
85}
86
87impl fmt::Debug for AccountAddress {
88    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
89        // Forward to the UpperHex impl with a "0x" prepended (the # flag).
90        write!(f, "{:#X}", self)
91    }
92}
93
94impl fmt::LowerHex for AccountAddress {
95    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
96        write!(f, "{}", hex::encode(&self.0))
97    }
98}
99
100impl fmt::UpperHex for AccountAddress {
101    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
102        write!(f, "{}", hex::encode_upper(&self.0))
103    }
104}
105
106impl TryFrom<&[u8]> for AccountAddress {
107    type Error = Error;
108
109    /// Tries to convert the provided byte array into Address.
110    fn try_from(bytes: &[u8]) -> Result<AccountAddress> {
111        ensure!(
112            bytes.len() == Self::LENGTH,
113            "The Address {:?} is of invalid length",
114            bytes
115        );
116        let mut addr = [0u8; Self::LENGTH];
117        addr.copy_from_slice(bytes);
118        Ok(AccountAddress(addr))
119    }
120}
121
122impl TryFrom<&[u8; AccountAddress::LENGTH]> for AccountAddress {
123    type Error = Error;
124
125    /// Tries to convert the provided byte array into Address.
126    fn try_from(bytes: &[u8; Self::LENGTH]) -> Result<AccountAddress> {
127        AccountAddress::try_from(&bytes[..])
128    }
129}
130
131impl TryFrom<Vec<u8>> for AccountAddress {
132    type Error = Error;
133
134    /// Tries to convert the provided byte buffer into Address.
135    fn try_from(bytes: Vec<u8>) -> Result<AccountAddress> {
136        AccountAddress::try_from(&bytes[..])
137    }
138}
139
140impl From<AccountAddress> for Vec<u8> {
141    fn from(addr: AccountAddress) -> Vec<u8> {
142        addr.0.to_vec()
143    }
144}
145
146impl From<&AccountAddress> for Vec<u8> {
147    fn from(addr: &AccountAddress) -> Vec<u8> {
148        addr.0.to_vec()
149    }
150}
151
152impl From<AccountAddress> for [u8; AccountAddress::LENGTH] {
153    fn from(addr: AccountAddress) -> Self {
154        addr.0
155    }
156}
157
158impl From<&AccountAddress> for [u8; AccountAddress::LENGTH] {
159    fn from(addr: &AccountAddress) -> Self {
160        addr.0
161    }
162}
163
164impl From<&AccountAddress> for String {
165    fn from(addr: &AccountAddress) -> String {
166        ::hex::encode(addr.as_ref())
167    }
168}
169
170impl TryFrom<String> for AccountAddress {
171    type Error = Error;
172
173    fn try_from(s: String) -> Result<AccountAddress> {
174        let bytes_out = ::hex::decode(s)?;
175        AccountAddress::try_from(bytes_out.as_slice())
176    }
177}
178
179impl FromStr for AccountAddress {
180    type Err = Error;
181
182    fn from_str(s: &str) -> Result<Self> {
183        let bytes_out = ::hex::decode(s)?;
184        AccountAddress::try_from(bytes_out.as_slice())
185    }
186}
187
188#[derive(Deserialize)]
189#[serde(rename = "AccountAddress")]
190struct DeserializeValue([u8; AccountAddress::LENGTH]);
191
192impl<'de> Deserialize<'de> for AccountAddress {
193    fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
194    where
195        D: Deserializer<'de>,
196    {
197        if deserializer.is_human_readable() {
198            let s = <String>::deserialize(deserializer)?;
199            AccountAddress::try_from(s).map_err(D::Error::custom)
200        } else {
201            let value = DeserializeValue::deserialize(deserializer)?;
202            Ok(AccountAddress::new(value.0))
203        }
204    }
205}
206
207impl Serialize for AccountAddress {
208    fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
209    where
210        S: Serializer,
211    {
212        if serializer.is_human_readable() {
213            self.to_string().serialize(serializer)
214        } else {
215            // See comment in deserialize.
216            serializer.serialize_newtype_struct("AccountAddress", &self.0)
217        }
218    }
219}