base16_rs/
base16.rs

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}