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 出现未预期的字符.
278    pub fn decode_number(input: &str) -> Result<u64, String> {
279        let mut input: String = input.to_string().replace(" ", "").replace("_", "");
280        input.truncate(16);
281        let mut output: u64 = 0;
282        for x in input.as_bytes().iter() {
283            match x {
284                b'0'..=b'9' => {
285                    output <<= 4;
286                    output |= (x - b'0') as u64;
287                }
288                b'a'..=b'f' => {
289                    output <<= 4;
290                    output |= (x - b'a' + 10) as u64;
291                }
292                b'A'..=b'F' => {
293                    output <<= 4;
294                    output |= (x - b'A' + 10) as u64;
295                }
296                _ => {
297                    return Err(iceyee_error::a!("出现未预期的字符"));
298                }
299            }
300        }
301        return Ok(output);
302    }
303}
304
305/// 进制编码.
306#[derive(Clone, Debug)]
307pub struct RadixEncoder;
308
309impl RadixEncoder {
310    /// 字符串转64位整数.
311    ///
312    /// - @exception 出现未预期的字符.
313    pub fn string_to_u64(input: &str) -> Result<u64, String> {
314        enum Radix {
315            Binary,
316            Octal,
317            Hexadecimal,
318        }
319        let mut input: String = input.to_string().replace(" ", "").replace("_", "");
320        let radix: Radix = if input.starts_with("0b") {
321            input = input[2..].to_string();
322            input.truncate(64);
323            Radix::Binary
324        } else if input.starts_with("0o") {
325            input = input[2..].to_string();
326            input.truncate(22);
327            Radix::Octal
328        } else if input.starts_with("0x") {
329            input = input[2..].to_string();
330            input.truncate(16);
331            Radix::Hexadecimal
332        } else {
333            Radix::Hexadecimal
334        };
335        let mut output: u64 = 0;
336        match radix {
337            Radix::Binary => {
338                for x in input.as_bytes().iter() {
339                    match x {
340                        b'0'..=b'1' => {
341                            output <<= 1;
342                            output |= (x - b'0') as u64;
343                        }
344                        _ => {
345                            return Err(iceyee_error::a!("出现未预期的字符"));
346                        }
347                    }
348                }
349            }
350            Radix::Octal => {
351                for x in input.as_bytes().iter() {
352                    match x {
353                        b'0'..=b'7' => {
354                            output <<= 3;
355                            output |= (x - b'0') as u64;
356                        }
357                        _ => {
358                            return Err(iceyee_error::a!("出现未预期的字符"));
359                        }
360                    }
361                }
362            }
363            Radix::Hexadecimal => {
364                for x in input.as_bytes().iter() {
365                    match x {
366                        b'0'..=b'9' => {
367                            output <<= 4;
368                            output |= (x - b'0') as u64;
369                        }
370                        b'a'..=b'f' => {
371                            output <<= 4;
372                            output |= (x - b'a' + 10) as u64;
373                        }
374                        b'A'..=b'F' => {
375                            output <<= 4;
376                            output |= (x - b'A' + 10) as u64;
377                        }
378                        _ => {
379                            return Err(iceyee_error::a!("出现未预期的字符"));
380                        }
381                    }
382                }
383            }
384        }
385        return Ok(output);
386    }
387
388    pub fn u64_to_bin(input: u64) -> String {
389        let mut input: u64 = input;
390        let mut output: String = String::new();
391        for _x in 0..64 {
392            let y: u8 = input as u8 & 0b1;
393            input >>= 1;
394            output.push((y + b'0') as char);
395        }
396        return output.chars().rev().collect();
397    }
398
399    pub fn u64_to_bin_(input: u64) -> String {
400        let mut input: u64 = input;
401        let mut output: String = String::new();
402        for x in 0..64 {
403            if x != 0 && x % 8 == 0 {
404                output.push('_');
405            }
406            let y: u8 = input as u8 & 0b1;
407            input >>= 1;
408            output.push((y + b'0') as char);
409        }
410        output.push('b');
411        output.push('0');
412        return output.chars().rev().collect();
413    }
414
415    pub fn u32_to_bin(input: u32) -> String {
416        let mut input: u32 = input;
417        let mut output: String = String::new();
418        for _x in 0..32 {
419            let y: u8 = input as u8 & 0b1;
420            input >>= 1;
421            output.push((y + b'0') as char);
422        }
423        return output.chars().rev().collect();
424    }
425
426    pub fn u32_to_bin_(input: u32) -> String {
427        let mut input: u32 = input;
428        let mut output: String = String::new();
429        for x in 0..32 {
430            if x != 0 && x % 8 == 0 {
431                output.push('_');
432            }
433            let y: u8 = input as u8 & 0b1;
434            input >>= 1;
435            output.push((y + b'0') as char);
436        }
437        output.push('b');
438        output.push('0');
439        return output.chars().rev().collect();
440    }
441
442    pub fn u16_to_bin(input: u16) -> String {
443        let mut input: u16 = input;
444        let mut output: String = String::new();
445        for _x in 0..16 {
446            let y: u8 = input as u8 & 0b1;
447            input >>= 1;
448            output.push((y + b'0') as char);
449        }
450        return output.chars().rev().collect();
451    }
452
453    pub fn u16_to_bin_(input: u16) -> String {
454        let mut input: u16 = input;
455        let mut output: String = String::new();
456        for x in 0..16 {
457            if x != 0 && x % 8 == 0 {
458                output.push('_');
459            }
460            let y: u8 = input as u8 & 0b1;
461            input >>= 1;
462            output.push((y + b'0') as char);
463        }
464        output.push('b');
465        output.push('0');
466        return output.chars().rev().collect();
467    }
468
469    pub fn u8_to_bin(input: u8) -> String {
470        let mut input: u8 = input;
471        let mut output: String = String::new();
472        for _x in 0..8 {
473            let y: u8 = input as u8 & 0b1;
474            input >>= 1;
475            output.push((y + b'0') as char);
476        }
477        return output.chars().rev().collect();
478    }
479
480    pub fn u8_to_bin_(input: u8) -> String {
481        let mut input: u8 = input;
482        let mut output: String = String::new();
483        for x in 0..8 {
484            if x != 0 && x % 8 == 0 {
485                output.push('_');
486            }
487            let y: u8 = input as u8 & 0b1;
488            input >>= 1;
489            output.push((y + b'0') as char);
490        }
491        output.push('b');
492        output.push('0');
493        return output.chars().rev().collect();
494    }
495
496    pub fn u64_to_oct(input: u64) -> String {
497        let mut input: u64 = input;
498        let mut output: String = String::new();
499        for _x in 0..22 {
500            let y: u8 = input as u8 & 0b111;
501            input >>= 3;
502            output.push((y + b'0') as char);
503        }
504        return output.chars().rev().collect();
505    }
506
507    pub fn u64_to_oct_(input: u64) -> String {
508        let mut input: u64 = input;
509        let mut output: String = String::new();
510        for x in 0..22 {
511            if x != 0 && false {
512                output.push('_');
513            }
514            let y: u8 = input as u8 & 0b111;
515            input >>= 3;
516            output.push((y + b'0') as char);
517        }
518        output.push('o');
519        output.push('0');
520        return output.chars().rev().collect();
521    }
522
523    pub fn u32_to_oct(input: u32) -> String {
524        let mut input: u32 = input;
525        let mut output: String = String::new();
526        for _x in 0..11 {
527            let y: u8 = input as u8 & 0b111;
528            input >>= 3;
529            output.push((y + b'0') as char);
530        }
531        return output.chars().rev().collect();
532    }
533
534    pub fn u32_to_oct_(input: u32) -> String {
535        let mut input: u32 = input;
536        let mut output: String = String::new();
537        for x in 0..11 {
538            if x != 0 && false {
539                output.push('_');
540            }
541            let y: u8 = input as u8 & 0b111;
542            input >>= 3;
543            output.push((y + b'0') as char);
544        }
545        output.push('o');
546        output.push('0');
547        return output.chars().rev().collect();
548    }
549
550    pub fn u16_to_oct(input: u16) -> String {
551        let mut input: u16 = input;
552        let mut output: String = String::new();
553        for _x in 0..6 {
554            let y: u8 = input as u8 & 0b111;
555            input >>= 3;
556            output.push((y + b'0') as char);
557        }
558        return output.chars().rev().collect();
559    }
560
561    pub fn u16_to_oct_(input: u16) -> String {
562        let mut input: u16 = input;
563        let mut output: String = String::new();
564        for x in 0..6 {
565            if x != 0 && false {
566                output.push('_');
567            }
568            let y: u8 = input as u8 & 0b111;
569            input >>= 3;
570            output.push((y + b'0') as char);
571        }
572        output.push('o');
573        output.push('0');
574        return output.chars().rev().collect();
575    }
576
577    pub fn u8_to_oct(input: u8) -> String {
578        let mut input: u8 = input;
579        let mut output: String = String::new();
580        for _x in 0..3 {
581            let y: u8 = input as u8 & 0b111;
582            input >>= 3;
583            output.push((y + b'0') as char);
584        }
585        return output.chars().rev().collect();
586    }
587
588    pub fn u8_to_oct_(input: u8) -> String {
589        let mut input: u8 = input;
590        let mut output: String = String::new();
591        for x in 0..3 {
592            if x != 0 && false {
593                output.push('_');
594            }
595            let y: u8 = input as u8 & 0b111;
596            input >>= 3;
597            output.push((y + b'0') as char);
598        }
599        output.push('o');
600        output.push('0');
601        return output.chars().rev().collect();
602    }
603
604    pub fn u64_to_hex(input: u64) -> String {
605        let mut input: u64 = input;
606        let mut output: String = String::new();
607        for _x in 0..16 {
608            let y: u8 = input as u8 & 0xF;
609            input >>= 4;
610            if y < 10 {
611                output.push((y + b'0') as char);
612            } else {
613                output.push((y - 10 + b'A') as char);
614            }
615        }
616        return output.chars().rev().collect();
617    }
618
619    pub fn u64_to_hex_(input: u64) -> String {
620        let mut input: u64 = input;
621        let mut output: String = String::new();
622        for x in 0..16 {
623            if x != 0 && x % 4 == 0 {
624                output.push('_');
625            }
626            let y: u8 = input as u8 & 0xF;
627            input >>= 4;
628            if y < 10 {
629                output.push((y + b'0') as char);
630            } else {
631                output.push((y - 10 + b'A') as char);
632            }
633        }
634        output.push('x');
635        output.push('0');
636        return output.chars().rev().collect();
637    }
638
639    pub fn u32_to_hex(input: u32) -> String {
640        let mut input: u32 = input;
641        let mut output: String = String::new();
642        for _x in 0..8 {
643            let y: u8 = input as u8 & 0xF;
644            input >>= 4;
645            if y < 10 {
646                output.push((y + b'0') as char);
647            } else {
648                output.push((y - 10 + b'A') as char);
649            }
650        }
651        return output.chars().rev().collect();
652    }
653
654    pub fn u32_to_hex_(input: u32) -> String {
655        let mut input: u32 = input;
656        let mut output: String = String::new();
657        for x in 0..8 {
658            if x != 0 && x % 4 == 0 {
659                output.push('_');
660            }
661            let y: u8 = input as u8 & 0xF;
662            input >>= 4;
663            if y < 10 {
664                output.push((y + b'0') as char);
665            } else {
666                output.push((y - 10 + b'A') as char);
667            }
668        }
669        output.push('x');
670        output.push('0');
671        return output.chars().rev().collect();
672    }
673
674    pub fn u16_to_hex(input: u16) -> String {
675        let mut input: u16 = input;
676        let mut output: String = String::new();
677        for _x in 0..4 {
678            let y: u8 = input as u8 & 0xF;
679            input >>= 4;
680            if y < 10 {
681                output.push((y + b'0') as char);
682            } else {
683                output.push((y - 10 + b'A') as char);
684            }
685        }
686        return output.chars().rev().collect();
687    }
688
689    pub fn u16_to_hex_(input: u16) -> String {
690        let mut input: u16 = input;
691        let mut output: String = String::new();
692        for x in 0..4 {
693            if x != 0 && x % 4 == 0 {
694                output.push('_');
695            }
696            let y: u8 = input as u8 & 0xF;
697            input >>= 4;
698            if y < 10 {
699                output.push((y + b'0') as char);
700            } else {
701                output.push((y - 10 + b'A') as char);
702            }
703        }
704        output.push('x');
705        output.push('0');
706        return output.chars().rev().collect();
707    }
708
709    pub fn u8_to_hex(input: u8) -> String {
710        let mut input: u8 = input;
711        let mut output: String = String::new();
712        for _x in 0..2 {
713            let y: u8 = input as u8 & 0xF;
714            input >>= 4;
715            if y < 10 {
716                output.push((y + b'0') as char);
717            } else {
718                output.push((y - 10 + b'A') as char);
719            }
720        }
721        return output.chars().rev().collect();
722    }
723
724    pub fn u8_to_hex_(input: u8) -> String {
725        let mut input: u8 = input;
726        let mut output: String = String::new();
727        for x in 0..2 {
728            if x != 0 && x % 4 == 0 {
729                output.push('_');
730            }
731            let y: u8 = input as u8 & 0xF;
732            input >>= 4;
733            if y < 10 {
734                output.push((y + b'0') as char);
735            } else {
736                output.push((y - 10 + b'A') as char);
737            }
738        }
739        output.push('x');
740        output.push('0');
741        return output.chars().rev().collect();
742    }
743}
744
745/// Url编码.
746
747#[derive(Debug, Clone)]
748pub struct UrlEncoder;
749
750impl UrlEncoder {
751    /// 编码.
752    pub fn encode(input: &str) -> String {
753        let input: String = input.to_string();
754        static TABLE: [char; 16] = [
755            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
756        ];
757        let mut output: String = String::new();
758        let input: &[u8] = input.as_bytes();
759        for x in input {
760            if *x == b' ' {
761                output.push('+');
762            } else if x.is_ascii_alphanumeric() || "$-_.".contains(*x as char) {
763                output.push(*x as char);
764            } else {
765                let high: u8 = (*x >> 4) & 0x0F;
766                let low: u8 = (*x >> 0) & 0x0F;
767                output.push('%');
768                output.push(TABLE[high as usize]);
769                output.push(TABLE[low as usize]);
770            }
771        }
772        return output;
773    }
774
775    /// 解码.
776    ///
777    /// - @exception 错误的格式.
778    /// - @exception 内容不是UTF-8编码.
779    pub fn decode(cipher: &str) -> Result<String, String> {
780        let cipher: String = cipher.to_string();
781        enum Status {
782            Normal,
783            High,
784            Low,
785        }
786        let mut plain: Vec<u8> = Vec::new();
787        let cipher: &[u8] = cipher.as_bytes();
788        let mut status: Status = Status::Normal;
789        let mut high: u8 = 0;
790        let mut low: u8;
791        for x in cipher {
792            match status {
793                Status::Normal => match *x {
794                    b'%' => status = Status::High,
795                    b'+' => plain.push(b' '),
796                    _ => plain.push(*x),
797                },
798                Status::High => match *x {
799                    b'0'..=b'9' => {
800                        status = Status::Low;
801                        high = *x - b'0';
802                    }
803                    b'a'..=b'f' => {
804                        status = Status::Low;
805                        high = *x - b'a' + 10;
806                    }
807                    b'A'..=b'F' => {
808                        status = Status::Low;
809                        high = *x - b'A' + 10;
810                    }
811                    _ => return Err(iceyee_error::a!("错误的格式")),
812                },
813                Status::Low => match *x {
814                    b'0'..=b'9' => {
815                        status = Status::Normal;
816                        low = *x - b'0';
817                        plain.push((high << 4) | (low << 0));
818                    }
819                    b'a'..=b'f' => {
820                        status = Status::Normal;
821                        low = *x - b'a' + 10;
822                        plain.push((high << 4) | (low << 0));
823                    }
824                    b'A'..=b'F' => {
825                        status = Status::Normal;
826                        low = *x - b'A' + 10;
827                        plain.push((high << 4) | (low << 0));
828                    }
829                    _ => return Err(iceyee_error::a!("错误的格式")),
830                },
831            }
832        }
833        match status {
834            Status::Normal => {}
835            _ => return Err(iceyee_error::a!("错误的格式")),
836        }
837        let plain: String =
838            String::from_utf8(plain).map_err(|_| iceyee_error::a!("内容不是UTF-8编码"))?;
839        return Ok(plain);
840    }
841}
842
843// Function.