1use std::str::FromStr;
16
17use super::{clean_0x, delete_left0, pad_left0};
18use super::{Bloom, BloomInput};
19use super::{H128, H160, H256, H264, H32, H512, H520, H64};
20use super::{U128, U256, U512, U64};
21
22pub trait LowerHex {
23 fn lower_hex(&self) -> String;
24 fn lower_hex_with_0x(&self) -> String;
25}
26
27pub trait ConvertType
28where
29 Self: ::std::marker::Sized,
30{
31 fn from_unaligned(_: &str) -> Option<Self>;
32}
33
34fn convert_u8_to_char(u: u8) -> char {
35 match u {
36 u if u < 10 => (b'0' + u) as char,
37 u if (10..16).contains(&u) => (b'a' + (u - 10)) as char,
38 _ => panic!("{} not bwtween 0 and 15", u),
39 }
40}
41
42impl<'a> LowerHex for &'a [u8] {
43 fn lower_hex(&self) -> String {
44 let sz = self.len();
45 let mut s = vec![0u8 as char; sz * 2];
46 for i in 0..sz {
47 s[i * 2] = convert_u8_to_char(self[i] / 16);
48 s[i * 2 + 1] = convert_u8_to_char(self[i] % 16);
49 }
50 s.into_iter().collect()
51 }
52
53 fn lower_hex_with_0x(&self) -> String {
54 let sz = self.len();
55 let mut s = vec![0u8 as char; sz * 2 + 2];
56 s[0] = '0';
57 s[1] = 'x';
58 for i in 0..sz {
59 s[i * 2 + 2] = convert_u8_to_char(self[i] / 16);
60 s[i * 2 + 3] = convert_u8_to_char(self[i] % 16);
61 }
62 s.into_iter().collect()
63 }
64}
65
66impl LowerHex for Vec<u8> {
67 fn lower_hex(&self) -> String {
68 let s = self as &[u8];
69 s.lower_hex()
70 }
71 fn lower_hex_with_0x(&self) -> String {
72 let s = self as &[u8];
73 s.lower_hex_with_0x()
74 }
75}
76
77macro_rules! add_cita_funcs {
78 ([$( ($name:ident, $bits:expr) ),+ ,]) => {
79 add_cita_funcs!([ $( ($name, $bits) ),+ ]);
80 };
81 ([$( ($name:ident, $bits:expr) ),+]) => {
82 $( add_cita_funcs!($name, $bits); )+
83 };
84 ($name:ident, $bits:expr) => {
85 impl LowerHex for $name {
86 #[inline]
87 fn lower_hex(&self) -> String {
88 format!("{:x}", self)
89 }
90
91 #[inline]
92 fn lower_hex_with_0x(&self) -> String {
93 format!("0x{:x}", self)
95 }
96 }
97
98 impl ConvertType for $name {
99 #[inline]
100 fn from_unaligned(s: &str) -> Option<Self> {
101 $name::from_str(
102 pad_left0(
103 delete_left0(clean_0x(s)), $bits/4usize).as_str())
104 .ok()
105 }
106 }
107 }
108}
109
110add_cita_funcs!([
111 (Bloom, 2048),
112 (H32, 32),
113 (H64, 64),
114 (H128, 128),
115 (H160, 160),
116 (H256, 256),
117 (H264, 264),
118 (H512, 512),
119 (H520, 520),
120 (U64, 64),
121 (U128, 128),
122 (U256, 256),
123 (U512, 512),
124]);
125
126pub trait BloomTools {
127 fn from_raw(_: &[u8]) -> Self;
128 fn contains_raw(&self, _: &[u8]) -> bool;
129 fn accrue_raw(&mut self, _: &[u8]);
130}
131
132impl BloomTools for Bloom {
133 fn from_raw(raw: &[u8]) -> Bloom {
134 Bloom::from(BloomInput::Raw(raw))
135 }
136
137 fn contains_raw(&self, raw: &[u8]) -> bool {
138 self.contains_input(BloomInput::Raw(raw))
139 }
140
141 fn accrue_raw(&mut self, raw: &[u8]) {
142 self.accrue(BloomInput::Raw(raw));
143 }
144}
145
146#[cfg(test)]
147mod tests {
148 use super::convert_u8_to_char;
149 use super::U128;
150 use super::{ConvertType, LowerHex};
151
152 #[test]
153 fn test_convert_u8_to_char() {
154 let mut x = vec![0u8 as char; 2];
155 for i in 0..256 {
156 {
157 let y = x.as_mut_slice();
158 y[0] = convert_u8_to_char(i as u8 / 16);
159 y[1] = convert_u8_to_char(i as u8 % 16);
160 }
161 let s: String = x.iter().collect();
162 assert_eq!(format!("{:02x}", i), s);
163 }
164 }
165
166 #[test]
167 fn test_lower_hex_for_u8() {
168 let x = vec![0u8, 127, 255];
169 let x_str = "007fff";
170 assert_eq!(x.lower_hex(), format!("{}", x_str));
171 assert_eq!(x.lower_hex_with_0x(), format!("0x{}", x_str));
172 }
173
174 #[test]
175 fn test_lower_hex_for_uint_and_hash() {
176 let validation = vec![
177 (0u64, "0"),
178 (10u64, "a"),
179 (2432902008176639999u64, "21c3677c82b3ffff"),
180 ];
181 for (x_uint, x_str) in validation.into_iter() {
182 assert_eq!(U128::from(x_uint).lower_hex(), format!("{}", x_str));
183 assert_eq!(
184 U128::from(x_uint).lower_hex_with_0x(),
185 format!("0x{}", x_str)
186 );
187 }
188 }
189
190 #[test]
191 fn test_from_unaligned() {
192 let validation = vec![
193 (2432902008176639999u64, "0x21c3677c82b3ffff"),
194 (2432902008176639999u64, "21c3677c82b3ffff"),
195 (2432902008176639999u64, "00000000021c3677c82b3ffff"),
196 (
197 2432902008176639999u64,
198 "000000000000000000000000000000000000000021c3677c82b3ffff",
199 ),
200 ];
201 for (i, s) in validation.into_iter() {
202 assert_eq!(U128::from(i), U128::from_unaligned(s).unwrap())
203 }
204 }
205}