1use std::{env::VarError, ops::Index};
2
3const BASE16_UPPER_TABLE: [u8; 16] = *b"0123456789ABCDEF";
4const BASE16_LOWER_TABLE: [u8; 16] = *b"0123456789abcdef";
5
6pub struct Decoder {}
7
8impl Decoder {
9 pub fn new() -> Self {
10 Decoder {}
11 }
12}
13
14impl Decoder {
15 #[inline]
16 pub fn decode_std(&self, src: &str) -> Result<Vec<u8>, usize> {
17 let mut dst = Vec::with_capacity(src.len() / 2);
18
19 let origin = src.to_lowercase();
20 for ch in origin.chars() {
21 let byte = ch as u8;
22 let r = BASE16_LOWER_TABLE.binary_search(&byte)?;
23 dst.push(r as u8)
24 }
25
26 let dst = dst
27 .chunks_exact(2)
28 .map(|bytes| {
29 let b1 = bytes[0];
30 let b2 = bytes[1];
31 b1 << 4 | b2
32 })
33 .collect::<Vec<u8>>();
34
35 Ok(dst)
36 }
37}
38
39pub struct Encoder {
40 typ: Type,
41}
42
43impl Encoder {
44 pub fn new(typ: Type) -> Self {
45 Encoder { typ }
46 }
47}
48
49impl Encoder {
50 pub fn encode_upper_to_string(&self, src: &[u8]) -> String {
51 match self.typ {
52 Type::StdEncoding => self
53 .encode_upper_std(src)
54 .into_iter()
55 .map(|b| b as char)
56 .collect(),
57 }
58 }
59
60 pub fn encode_lower_to_string(&self, src: &[u8]) -> String {
61 match self.typ {
62 Type::StdEncoding => self
63 .encode_lower_std(src)
64 .into_iter()
65 .map(|b| b as char)
66 .collect(),
67 }
68 }
69
70 #[inline]
71 fn encode_upper_std(&self, src: &[u8]) -> Vec<u8> {
72 self.encode_std(src, EncodeConfig::UPPER)
73 }
74
75 #[inline]
76 fn encode_lower_std(&self, src: &[u8]) -> Vec<u8> {
77 self.encode_std(src, EncodeConfig::LOWER)
78 }
79
80 #[inline]
81 fn encode_std(&self, src: &[u8], cfg: EncodeConfig) -> Vec<u8> {
82 let table = if cfg == EncodeConfig::LOWER {
83 BASE16_LOWER_TABLE
84 } else {
85 BASE16_UPPER_TABLE
86 };
87
88 let mut dst = Vec::with_capacity(src.len() * 2);
89 for b in src.iter() {
90 let byte = *b;
91 dst.push(table[(byte >> 4) as usize]);
92 dst.push(table[(byte & 0x0F) as usize]);
93 }
94 dst
95 }
96}
97
98pub enum Type {
99 StdEncoding,
100}
101
102#[derive(PartialEq)]
103enum EncodeConfig {
104 UPPER,
105 LOWER,
106}
107
108#[cfg(test)]
109mod encode_tests {
110 use super::*;
111 use crate::base16::Type::StdEncoding;
112
113 #[test]
114 fn empty() {
115 let buf: Vec<u8> = Vec::from("");
116 let encoder = Encoder::new(StdEncoding);
117 let result = encoder.encode_upper_to_string(&buf);
118 assert_eq!(result, "");
119 }
120
121 #[test]
122 fn number() {
123 let buf: Vec<u8> = Vec::from("0123456789");
124 let encoder = Encoder::new(StdEncoding);
125 let result = encoder.encode_upper_to_string(&buf);
126 assert_eq!(result, "30313233343536373839");
127 }
128
129 #[test]
130 fn alpha() {
131 let buf: Vec<u8> = Vec::from("abcdefghijklnmopqrstuvwxyz");
132 let encoder = Encoder::new(StdEncoding);
133 let result = encoder.encode_upper_to_string(&buf);
134 assert_eq!(
135 result,
136 "6162636465666768696A6B6C6E6D6F707172737475767778797A"
137 );
138 }
139
140 #[test]
141 fn enter() {
142 let buf: Vec<u8> = Vec::from(
143 r#"abcdefghijklnmo
144pqrstuvwxyz"#,
145 );
146 let encoder = Encoder::new(StdEncoding);
147 let result = encoder.encode_upper_to_string(&buf);
148 assert_eq!(
149 result,
150 "6162636465666768696A6B6C6E6D6F0A707172737475767778797A"
151 );
152 }
153}
154#[cfg(test)]
155mod decode_tests {
156 use super::*;
157 use crate::base16::Type::StdEncoding;
158
159 #[test]
160 fn empty() {
161 let buf: String = String::from("");
162 let decoder = Decoder::new();
163 let result = decoder.decode_std(&buf);
164 assert_eq!(result, Ok(Vec::from("")));
165 }
166
167 #[test]
168 fn number() {
169 let buf: String = String::from("30313233343536373839");
170 let decoder = Decoder::new();
171 let result = decoder.decode_std(&buf);
172 assert_eq!(result, Ok(Vec::from("0123456789")));
173 }
174
175 #[test]
176 fn alpha() {
177 let buf: String = String::from("6162636465666768696A6B6C6E6D6F707172737475767778797A");
178 let decoder = Decoder::new();
179 let result = decoder.decode_std(&buf);
180 assert_eq!(result, Ok(Vec::from("abcdefghijklnmopqrstuvwxyz")));
181 }
182 #[test]
183 fn error() {
184 let buf: String = String::from("AFGHHFJ");
185 let decoder = Decoder::new();
186 let result = decoder.decode_std(&buf);
187 assert_eq!(result, Err(16));
188 }
189
190 #[test]
191 fn enter() {
192 let buf: String = String::from("6162636465666768696A6B6C6E6D6F0A707172737475767778797A");
193 let decoder = Decoder::new();
194 let result = decoder.decode_std(&buf);
195 assert_eq!(
196 result,
197 Ok(Vec::from(
198 r#"abcdefghijklnmo
199pqrstuvwxyz"#
200 ))
201 );
202 }
203}