1use super::errors::{DecodingError, EncodingError};
9
10use cfx_types::address_util::{self, AddressUtil};
11use std::{fmt, string::ToString};
12
13pub const CHARSET_SIZE: usize = 32;
14
15pub const RESERVED_BITS_MASK: u8 = 0xf8;
16
17pub const SIZE_MASK: u8 = 0x07;
30pub const SIZE_160: u8 = 0x00;
31pub const SIZE_192: u8 = 0x01;
34pub const SIZE_224: u8 = 0x02;
35pub const SIZE_256: u8 = 0x03;
36pub const SIZE_320: u8 = 0x04;
37pub const SIZE_384: u8 = 0x05;
38pub const SIZE_448: u8 = 0x06;
39pub const SIZE_512: u8 = 0x07;
40
41#[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
42pub enum Network {
43 Main,
45 Test,
47 Id(u64),
49}
50
51const MAINNET_PREFIX: &str = "cfx";
53const TESTNET_PREFIX: &str = "cfxtest";
54const NETWORK_ID_PREFIX: &str = "net";
55const RESERVED_NETWORK_IDS: [u64; 2] = [1, 1029];
57
58#[derive(Debug, PartialEq, Eq, Clone)]
59pub enum AddressType {
60 Builtin,
61 Contract,
62 Null,
63 User,
64 Unknown,
65}
66
67impl fmt::Display for Network {
68 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
69 match self.to_prefix() {
70 Err(EncodingError::InvalidNetworkId(network_id)) => {
71 write!(f, "invalid network prefix net{}", network_id)
72 }
73 Err(_) => unreachable!(),
74 Ok(prefix) => write!(f, "{}", prefix),
75 }
76 }
77}
78
79impl Network {
80 pub fn to_prefix(&self) -> Result<String, EncodingError> {
81 match self {
82 Network::Main => Ok(MAINNET_PREFIX.into()),
83 Network::Test => Ok(TESTNET_PREFIX.into()),
84 Network::Id(network_id) => {
85 if RESERVED_NETWORK_IDS.contains(network_id) {
86 Err(EncodingError::InvalidNetworkId(*network_id))
87 } else {
88 Ok(format!("net{}", network_id))
89 }
90 }
91 }
92 }
93
94 pub fn from_prefix(prefix: &str) -> Result<Self, DecodingError> {
95 match prefix {
96 MAINNET_PREFIX => Ok(Network::Main),
97 TESTNET_PREFIX => Ok(Network::Test),
98 _ => {
99 let maybe_network_id = if !prefix.starts_with(NETWORK_ID_PREFIX)
100 {
101 None
102 } else {
103 match prefix[NETWORK_ID_PREFIX.len()..].parse::<u64>() {
104 Err(_) => None,
105 Ok(network_id) => {
106 if RESERVED_NETWORK_IDS.contains(&network_id) {
108 None
109 } else {
110 Some(network_id)
111 }
112 }
113 }
114 };
115
116 match maybe_network_id {
117 None => {
118 Err(DecodingError::InvalidPrefix(prefix.to_string()))
119 }
120 Some(network_id) => Ok(Network::Id(network_id)),
121 }
122 }
123 }
124 }
125}
126
127impl AddressType {
128 const BUILTIN: &'static str = "builtin";
129 const CONTRACT: &'static str = "contract";
130 const NULL: &'static str = "null";
131 const UNKNOWN: &'static str = "unknown";
132 const USER: &'static str = "user";
133
134 pub fn parse(text: &str) -> Result<Self, DecodingError> {
135 if text == Self::BUILTIN {
136 Ok(Self::Builtin)
137 } else if text == Self::CONTRACT {
138 Ok(Self::Contract)
139 } else if text == Self::NULL {
140 Ok(Self::Null)
141 } else if text == Self::USER {
142 Ok(Self::User)
143 } else {
144 Ok(Self::Unknown)
145 }
146 }
147
148 pub fn from_address<T: AddressUtil>(
149 address_hex: &T,
150 ) -> Result<Self, EncodingError> {
151 match address_hex.address_type_bits() {
152 address_util::TYPE_BITS_BUILTIN => {
153 if address_hex.is_null_address() {
154 Ok(Self::Null)
155 } else {
156 Ok(Self::Builtin)
157 }
158 }
159 address_util::TYPE_BITS_CONTRACT => Ok(Self::Contract),
160 address_util::TYPE_BITS_USER_ACCOUNT => Ok(Self::User),
161 _ => Ok(Self::Unknown),
162 }
163 }
164
165 pub fn to_str(&self) -> &'static str {
166 match self {
167 Self::Builtin => Self::BUILTIN,
168 Self::Contract => Self::CONTRACT,
169 Self::Null => Self::NULL,
170 Self::User => Self::USER,
171 Self::Unknown => Self::UNKNOWN,
172 }
173 }
174}
175
176impl ToString for AddressType {
177 fn to_string(&self) -> String { self.to_str().into() }
178}