1use crate::{error::FromStrError, H160, H256, H512, H520};
2
3pub(crate) const DICT_HEX_ERROR: u8 = u8::MAX;
4pub(crate) static DICT_HEX_LO: [u8; 256] = {
5 const ____: u8 = DICT_HEX_ERROR;
6 [
7 ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____,
8 ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____,
9 ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____,
10 ____, ____, ____, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, ____, ____,
11 ____, ____, ____, ____, ____, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, ____, ____, ____, ____,
12 ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____,
13 ____, ____, ____, ____, ____, ____, ____, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, ____, ____,
14 ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____,
15 ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____,
16 ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____,
17 ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____,
18 ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____,
19 ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____,
20 ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____,
21 ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____,
22 ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____,
23 ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____,
24 ____,
25 ]
26};
27pub(crate) static DICT_HEX_HI: [u8; 256] = {
28 const ____: u8 = DICT_HEX_ERROR;
29 [
30 ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____,
31 ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____,
32 ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____,
33 ____, ____, ____, 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, ____, ____,
34 ____, ____, ____, ____, ____, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, ____, ____, ____, ____,
35 ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____,
36 ____, ____, ____, ____, ____, ____, ____, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, ____, ____,
37 ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____,
38 ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____,
39 ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____,
40 ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____,
41 ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____,
42 ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____,
43 ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____,
44 ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____,
45 ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____,
46 ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____,
47 ____,
48 ]
49};
50
51macro_rules! impl_std_str_fromstr {
52 ($name:ident, $bytes_size:expr) => {
53 impl ::std::str::FromStr for $name {
54 type Err = FromStrError;
55 fn from_str(input: &str) -> Result<Self, Self::Err> {
56 let len = input.as_bytes().len();
57 if len != $bytes_size * 2 {
58 return Err(FromStrError::InvalidLength(len));
59 }
60 let mut ret = Self::default();
61 for (idx, chr) in input.bytes().enumerate() {
62 let val = if idx % 2 == 0 {
63 DICT_HEX_HI[usize::from(chr)]
64 } else {
65 DICT_HEX_LO[usize::from(chr)]
66 };
67 if val == DICT_HEX_ERROR {
68 return Err(FromStrError::InvalidCharacter { chr, idx });
69 }
70 ret.0[idx / 2] |= val;
71 }
72 Ok(ret)
73 }
74 }
75 };
76}
77
78macro_rules! impl_from_trimmed_str {
79 ($name:ident, $bytes_size:expr, $use_stmt:expr, $bytes_size_stmt:expr) => {
80 impl $name {
81 #[doc = $use_stmt]
95 #[doc = $bytes_size_stmt]
96 pub fn from_trimmed_str(input: &str) -> Result<Self, FromStrError> {
124 let bytes = input.as_bytes();
125 let len = bytes.len();
126 if len > $bytes_size * 2 {
127 Err(FromStrError::InvalidLength(len))
128 } else if len == 0 {
129 Ok(Self::default())
130 } else if bytes[0] == b'0' {
131 if len == 1 {
132 Ok(Self::default())
133 } else {
134 Err(FromStrError::InvalidCharacter { chr: b'0', idx: 0 })
135 }
136 } else {
137 let mut ret = Self::default();
138 let mut idx = 0;
139 let mut unit_idx = ($bytes_size * 2 - len) / 2;
140 let mut high = len % 2 == 0;
141 for chr in input.bytes() {
142 let val = if high {
143 DICT_HEX_HI[usize::from(chr)]
144 } else {
145 DICT_HEX_LO[usize::from(chr)]
146 };
147 if val == DICT_HEX_ERROR {
148 return Err(FromStrError::InvalidCharacter { chr, idx });
149 }
150 idx += 1;
151 ret.0[unit_idx] |= val;
152 if high {
153 high = false;
154 } else {
155 high = true;
156 unit_idx += 1;
157 }
158 }
159 Ok(ret)
160 }
161 }
162 }
163 };
164 ($name:ident, $bytes_size:expr) => {
165 impl_from_trimmed_str!(
166 $name,
167 $bytes_size,
168 concat!("use ckb_fixed_hash_core::", stringify!($name), " as Hash;"),
169 concat!("const BYTES_SIZE: usize = ", stringify!($bytes_size), ";")
170 );
171 };
172}
173
174impl_std_str_fromstr!(H160, 20);
175impl_std_str_fromstr!(H256, 32);
176impl_std_str_fromstr!(H512, 64);
177impl_std_str_fromstr!(H520, 65);
178
179impl_from_trimmed_str!(H160, 20);
180impl_from_trimmed_str!(H256, 32);
181impl_from_trimmed_str!(H512, 64);
182impl_from_trimmed_str!(H520, 65);