iceyee_encoder/
lib.rs

1// **************************************************
2// *  Author: Iceyee                                *
3// *  Mail: iceyee.studio@qq.com                    *
4// *  Git: https://github.com/iceyee                *
5// **************************************************
6//
7
8//! 编码器.
9
10// Use.
11
12// Enum.
13
14// Trait.
15
16// Struct.
17
18/// Base64编码.
19#[derive(Debug, Clone)]
20pub struct Base64Encoder;
21
22impl Base64Encoder {
23    /// 编码.
24    pub fn encode(input: &[u8]) -> String {
25        let input_length: usize = input.len();
26        if input_length == 0 {
27            return "".to_string();
28        }
29        let valid_length: usize = match input_length % 3 {
30            0 => input_length / 3 * 4,
31            1 => input_length / 3 * 4 + 2,
32            2 => input_length / 3 * 4 + 3,
33            _ => panic!(""),
34        };
35        const TABLE: &[u8] =
36            "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".as_bytes();
37        let mut output: Vec<u8> = Vec::with_capacity(input_length * 2 + 1);
38        let m: usize = valid_length / 4;
39        for x in 0..m {
40            // let x0: usize = x * 4 + 0;
41            // let x1: usize = x * 4 + 1;
42            // let x2: usize = x * 4 + 2;
43            // let x3: usize = x * 4 + 3;
44            let y0: usize = x * 3 + 0;
45            let y1: usize = x * 3 + 1;
46            let y2: usize = x * 3 + 2;
47            let mut v1: u8;
48            let mut v2: u8;
49            v1 = (input[y0] & 0b11111100) >> 2;
50            v2 = 0;
51            output.push(TABLE[(v1 | v2) as usize]);
52            v1 = (input[y0] & 0b00000011) << 4;
53            v2 = (input[y1] & 0b11110000) >> 4;
54            output.push(TABLE[(v1 | v2) as usize]);
55            v1 = (input[y1] & 0b00001111) << 2;
56            v2 = (input[y2] & 0b11000000) >> 6;
57            output.push(TABLE[(v1 | v2) as usize]);
58            v1 = (input[y2] & 0b00111111) >> 0;
59            v2 = 0;
60            output.push(TABLE[(v1 | v2) as usize]);
61        }
62        // let x0: usize = m * 4 + 0;
63        // let x1: usize = m * 4 + 1;
64        // let x2: usize = m * 4 + 2;
65        // let x3: usize = m * 4 + 3;
66        let y0: usize = m * 3 + 0;
67        let y1: usize = m * 3 + 1;
68        // let y2: usize = m * 3 + 2;
69        let mut v1: u8;
70        let mut v2: u8;
71        if input_length % 3 == 1 {
72            v1 = (input[y0] & 0b11111100) >> 2;
73            v2 = 0;
74            output.push(TABLE[(v1 | v2) as usize]);
75            v1 = (input[y0] & 0b00000011) << 4;
76            v2 = 0;
77            output.push(TABLE[(v1 | v2) as usize]);
78            output.push(b'=');
79            output.push(b'=');
80        } else if input_length % 3 == 2 {
81            v1 = (input[y0] & 0b11111100) >> 2;
82            v2 = 0;
83            output.push(TABLE[(v1 | v2) as usize]);
84            v1 = (input[y0] & 0b00000011) << 4;
85            v2 = (input[y1] & 0b11110000) >> 4;
86            output.push(TABLE[(v1 | v2) as usize]);
87            v1 = (input[y1] & 0b00001111) << 2;
88            v2 = 0;
89            output.push(TABLE[(v1 | v2) as usize]);
90            output.push(b'=');
91        }
92        let output: String = String::from_utf8(output).unwrap();
93        return output;
94    }
95
96    /// 解码.
97    ///
98    /// - @exception 无效的长度.
99    /// - @exception 出现未预期的字符.
100    pub fn decode(input: &str) -> Result<Vec<u8>, String> {
101        let input: String = input.to_string();
102        const TABLE: [u8; 0x100] = [
103            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
104            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
105            255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63, 52, 53, 54, 55, 56,
106            57, 58, 59, 60, 61, 255, 255, 255, 255, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
107            10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255,
108            255, 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
109            45, 46, 47, 48, 49, 50, 51, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
110            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
111            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
112            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
113            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
114            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
115            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
116            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
117            255, 255,
118        ];
119        let length: usize = input.len();
120        if length == 0 {
121            return Ok(Vec::<u8>::new());
122        }
123        if length % 4 != 0 {
124            return Err(iceyee_error::a!("无效的长度"));
125        }
126        let input_data: &[u8] = input.as_bytes();
127        for x in 0..input_data.len() {
128            let c: u8 = input_data[x];
129            if TABLE[c as usize] != 255 || c == b'=' && input_data.len() <= x + 2 {
130                // 正常.
131            } else {
132                return Err(iceyee_error::a!("出现未预期的字符"));
133            }
134        }
135        let new_length: usize = if input_data[input_data.len() - 2] == b'=' {
136            (length - 2) / 4 * 3 + 1
137        } else if input_data[input_data.len() - 1] == b'=' {
138            (length - 1) / 4 * 3 + 2
139        } else {
140            length / 4 * 3
141        };
142        let mut output: Vec<u8> = Vec::new();
143        let m: usize = new_length / 3;
144        for x in 0..m {
145            // let x0: usize = x * 3 + 0;
146            // let x1: usize = x * 3 + 1;
147            // let x2: usize = x * 3 + 2;
148            let y0: usize = x * 4 + 0;
149            let y1: usize = x * 4 + 1;
150            let y2: usize = x * 4 + 2;
151            let y3: usize = x * 4 + 3;
152            let mut v1: u8;
153            let mut v2: u8;
154            v1 = (TABLE[input_data[y0] as usize] & 0b00111111) << 2;
155            v2 = (TABLE[input_data[y1] as usize] & 0b00110000) >> 4;
156            output.push(v1 | v2);
157            v1 = (TABLE[input_data[y1] as usize] & 0b00001111) << 4;
158            v2 = (TABLE[input_data[y2] as usize] & 0b00111100) >> 2;
159            output.push(v1 | v2);
160            v1 = (TABLE[input_data[y2] as usize] & 0b00000011) << 6;
161            v2 = (TABLE[input_data[y3] as usize] & 0b00111111) >> 0;
162            output.push(v1 | v2);
163        }
164        // let x0: usize = m * 3 + 0;
165        // let x1: usize = m * 3 + 1;
166        // let x2: usize = m * 3 + 2;
167        let y0: usize = m * 4 + 0;
168        let y1: usize = m * 4 + 1;
169        let y2: usize = m * 4 + 2;
170        // let y3: usize = m * 4 + 3;
171        let mut v1: u8;
172        let mut v2: u8;
173        if new_length % 3 == 1 {
174            v1 = (TABLE[input_data[y0] as usize] & 0b00111111) << 2;
175            v2 = (TABLE[input_data[y1] as usize] & 0b00110000) >> 4;
176            output.push(v1 | v2);
177        } else if new_length % 3 == 2 {
178            v1 = (TABLE[input_data[y0] as usize] & 0b00111111) << 2;
179            v2 = (TABLE[input_data[y1] as usize] & 0b00110000) >> 4;
180            output.push(v1 | v2);
181            v1 = (TABLE[input_data[y1] as usize] & 0b00001111) << 4;
182            v2 = (TABLE[input_data[y2] as usize] & 0b00111100) >> 2;
183            output.push(v1 | v2);
184        }
185        return Ok(output);
186    }
187}
188
189/// 十六进制编码.
190#[derive(Debug, Clone)]
191pub struct HexEncoder;
192
193impl HexEncoder {
194    /// 编码.
195    pub fn encode(input: &[u8]) -> String {
196        static TABLE: [char; 16] = [
197            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
198        ];
199        let mut output: String = String::new();
200        for x in input {
201            let high: u8 = (x >> 4) & 0x0F;
202            let low: u8 = (x >> 0) & 0x0F;
203            output.push(TABLE[high as usize]);
204            output.push(TABLE[low as usize]);
205        }
206        return output;
207    }
208
209    /// 解码.
210    ///
211    /// - @exception 无效的长度.
212    /// - @exception 出现未预期的字符.
213    pub fn decode(input: &str) -> Result<Vec<u8>, String> {
214        let input: String = input.to_string();
215        let length: usize = input.len();
216        if length % 2 != 0 {
217            return Err(iceyee_error::a!("无效的长度"));
218        }
219        let mut output: Vec<u8> = Vec::new();
220        let input: &[u8] = input.as_bytes();
221        let mut high: u8;
222        let mut low: u8;
223        for x in 0..(length / 2) {
224            match input[x * 2] {
225                b'0'..=b'9' => {
226                    high = input[x * 2] - b'0';
227                }
228                b'a'..=b'f' => {
229                    high = input[x * 2] - b'a' + 10;
230                }
231                b'A'..=b'F' => {
232                    high = input[x * 2] - b'A' + 10;
233                }
234                _ => return Err(iceyee_error::a!("出现未预期的字符")),
235            }
236            match input[x * 2 + 1] {
237                b'0'..=b'9' => {
238                    low = input[x * 2 + 1] - b'0';
239                }
240                b'a'..=b'f' => {
241                    low = input[x * 2 + 1] - b'a' + 10;
242                }
243                b'A'..=b'F' => {
244                    low = input[x * 2 + 1] - b'A' + 10;
245                }
246                _ => return Err(iceyee_error::a!("出现未预期的字符")),
247            }
248            let b: u8 = (high << 4) | (low << 0);
249            output.push(b);
250        }
251        return Ok(output);
252    }
253
254    /// 编码64位整数.
255    pub fn encode_number(mut input: u64) -> String {
256        static TABLE: [char; 16] = [
257            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
258        ];
259        if input == 0 {
260            return "0".to_string();
261        }
262        let mut output: Vec<u8> = Vec::new();
263        while input != 0 {
264            let digit: usize = (input & 0xF) as usize;
265            output.push(TABLE[digit] as u8);
266            input = input >> 4;
267            let digit: usize = (input & 0xF) as usize;
268            output.push(TABLE[digit] as u8);
269            input = input >> 4;
270        }
271        output.reverse();
272        return String::from_utf8(output).unwrap();
273    }
274
275    /// 解码64位整数.
276    ///
277    /// - @exception 长度超过16.
278    /// - @exception 出现未预期的字符.
279    pub fn decode_number(input: &str) -> Result<u64, String> {
280        let v1: &[u8] = input.as_bytes();
281        if 16 < v1.len() {
282            // 长度过长.
283            return Err(iceyee_error::a!("长度超过16"));
284        }
285        let mut output: u64 = 0;
286        for x in 0..v1.len() {
287            match v1[x] {
288                b'0'..=b'9' => {
289                    output <<= 4;
290                    output |= (v1[x] - b'0') as u64;
291                }
292                b'A'..=b'F' => {
293                    output <<= 4;
294                    output |= (v1[x] - b'A' + 10) as u64;
295                }
296                b'a'..=b'f' => {
297                    output <<= 4;
298                    output |= (v1[x] - b'a' + 10) as u64;
299                }
300                _ => {
301                    return Err(iceyee_error::a!("出现未预期的字符"));
302                }
303            }
304        }
305        return Ok(output);
306    }
307}
308
309/// Url编码.
310
311#[derive(Debug, Clone)]
312pub struct UrlEncoder;
313
314impl UrlEncoder {
315    /// 编码.
316    pub fn encode(input: &str) -> String {
317        let input: String = input.to_string();
318        static TABLE: [char; 16] = [
319            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
320        ];
321        let mut output: String = String::new();
322        let input: &[u8] = input.as_bytes();
323        for x in input {
324            if *x == b' ' {
325                output.push('+');
326            } else if x.is_ascii_alphanumeric() || "$-_.".contains(*x as char) {
327                output.push(*x as char);
328            } else {
329                let high: u8 = (*x >> 4) & 0x0F;
330                let low: u8 = (*x >> 0) & 0x0F;
331                output.push('%');
332                output.push(TABLE[high as usize]);
333                output.push(TABLE[low as usize]);
334            }
335        }
336        return output;
337    }
338
339    /// 解码.
340    ///
341    /// - @exception 错误的格式.
342    /// - @exception 内容不是UTF-8编码.
343    pub fn decode(cipher: &str) -> Result<String, String> {
344        let cipher: String = cipher.to_string();
345        enum Status {
346            Normal,
347            High,
348            Low,
349        }
350        let mut plain: Vec<u8> = Vec::new();
351        let cipher: &[u8] = cipher.as_bytes();
352        let mut status: Status = Status::Normal;
353        let mut high: u8 = 0;
354        let mut low: u8;
355        for x in cipher {
356            match status {
357                Status::Normal => match *x {
358                    b'%' => status = Status::High,
359                    b'+' => plain.push(b' '),
360                    _ => plain.push(*x),
361                },
362                Status::High => match *x {
363                    b'0'..=b'9' => {
364                        status = Status::Low;
365                        high = *x - b'0';
366                    }
367                    b'a'..=b'f' => {
368                        status = Status::Low;
369                        high = *x - b'a' + 10;
370                    }
371                    b'A'..=b'F' => {
372                        status = Status::Low;
373                        high = *x - b'A' + 10;
374                    }
375                    _ => return Err(iceyee_error::a!("错误的格式")),
376                },
377                Status::Low => match *x {
378                    b'0'..=b'9' => {
379                        status = Status::Normal;
380                        low = *x - b'0';
381                        plain.push((high << 4) | (low << 0));
382                    }
383                    b'a'..=b'f' => {
384                        status = Status::Normal;
385                        low = *x - b'a' + 10;
386                        plain.push((high << 4) | (low << 0));
387                    }
388                    b'A'..=b'F' => {
389                        status = Status::Normal;
390                        low = *x - b'A' + 10;
391                        plain.push((high << 4) | (low << 0));
392                    }
393                    _ => return Err(iceyee_error::a!("错误的格式")),
394                },
395            }
396        }
397        match status {
398            Status::Normal => {}
399            _ => return Err(iceyee_error::a!("错误的格式")),
400        }
401        let plain: String =
402            String::from_utf8(plain).map_err(|_| iceyee_error::a!("内容不是UTF-8编码"))?;
403        return Ok(plain);
404    }
405}
406
407// Function.