bases64/
bases.rs

1use std::collections::HashMap;
2
3pub struct Bases{}
4
5impl Bases{
6    fn standard_code(&self) -> HashMap<i32, char>{
7        //
8        let standard: HashMap<i32, char> = [
9            (0, 'A'),
10            (1, 'B'),
11            (2, 'C'),
12            (3, 'D'),
13            (4, 'E'),
14            (5, 'F'),
15            (6, 'G'),
16            (7, 'H'),
17            (8, 'I'),
18            (9, 'J'),
19            (10, 'K'),
20            (11, 'L'),
21            (12, 'M'),
22            (13, 'N'),
23            (14, 'O'),
24            (15, 'P'),
25            (16, 'Q'),
26            (17, 'R'),
27            (18, 'S'),
28            (19, 'T'),
29            (20, 'U'),
30            (21, 'V'),
31            (22, 'W'),
32            (23, 'X'),
33            (24, 'Y'),
34            (25, 'Z'),
35            (26, 'a'),
36            (27, 'b'),
37            (28, 'c'),
38            (29, 'd'),
39            (30, 'e'),
40            (31, 'f'),
41            (32, 'g'),
42            (33, 'h'),
43            (34, 'i'),
44            (35, 'j'),
45            (36, 'k'),
46            (37, 'l'),
47            (38, 'm'),
48            (39, 'n'),
49            (40, 'o'),
50            (41, 'p'),
51            (42, 'q'),
52            (43, 'r'),
53            (44, 's'),
54            (45, 't'),
55            (46, 'u'),
56            (47, 'v'),
57            (48, 'w'),
58            (49, 'x'),
59            (50, 'y'),
60            (51, 'z'),
61            (52, '0'),
62            (53, '1'),
63            (54, '2'),
64            (55, '3'),
65            (56, '4'),
66            (57, '5'),
67            (58, '6'),
68            (59, '7'),
69            (60, '8'),
70            (61, '9'),
71            (62, '+'),
72            (63, '/'),
73            (65, '=')
74        ].iter().cloned().collect();
75        standard
76    }
77
78    fn standard_code_contrary(&self) -> HashMap<char, i32>{
79        //
80        let standard: HashMap<char, i32> = [
81            ('A', 0),
82            ('B', 1),
83            ('C', 2),
84            ('D', 3),
85            ('E', 4),
86            ('F', 5),
87            ('G', 6),
88            ('H', 7),
89            ('I', 8),
90            ('J', 9),
91            ('K', 10),
92            ('L', 11),
93            ('M', 12),
94            ('N', 13),
95            ('O', 14),
96            ('P', 15),
97            ('Q', 16),
98            ('R', 17),
99            ('S', 18),
100            ('T', 19),
101            ('U', 20),
102            ('V', 21),
103            ('W', 22),
104            ('X', 23),
105            ('Y', 24),
106            ('Z', 25),
107            ('a', 26),
108            ('b', 27),
109            ('c', 28),
110            ('d', 29),
111            ('e', 30),
112            ('f', 31),
113            ('g', 32),
114            ('h', 33),
115            ('i', 34),
116            ('j', 35),
117            ('k', 36),
118            ('l', 37),
119            ('m', 38),
120            ('n', 39),
121            ('o', 40),
122            ('p', 41),
123            ('q', 42),
124            ('r', 43),
125            ('s', 44),
126            ('t', 45),
127            ('u', 46),
128            ('v', 47),
129            ('w', 48),
130            ('x', 49),
131            ('y', 50),
132            ('z', 51),
133            ('0', 52),
134            ('1', 53),
135            ('2', 54),
136            ('3', 55),
137            ('4', 56),
138            ('5', 57),
139            ('6', 58),
140            ('7', 59),
141            ('8', 60),
142            ('9', 61),
143            ('+', 62),
144            ('/', 63),
145            ('=', 65),
146        ].iter().cloned().collect();
147        standard
148    }
149
150    fn standard_code_url(&self) -> HashMap<i32, char>{
151        // for url
152        let mut standard = self.standard_code();
153        standard.insert(62, '-');
154        standard.insert(63, '_');
155        standard
156    }
157
158    fn standard_code_contrary_url(&self) -> HashMap<char, i32>{
159        // for url
160        let mut standard = self.standard_code_contrary();
161        standard.remove(&'+');
162        standard.remove(&'/');
163        standard.insert('-', 62);
164        standard.insert('_', 63);
165        standard
166    }
167
168    pub fn encode(&self, value: &str) -> String{
169        let value_bytes = value.as_bytes();
170        let base_encode_value = self.binary_trans(value_bytes, false);
171        let mut result = String::from("");
172        for i in base_encode_value{
173            result.push(i);
174        }
175        result
176    }
177
178    pub fn encode_url(&self, value: &str) -> String{
179        // encode for url
180        let value_bytes = value.as_bytes();
181        let base_encode_value = self.binary_trans(value_bytes, true);
182        let mut result = String::from("");
183        for i in base_encode_value{
184            result.push(i);
185        }
186        result
187    }
188
189    pub fn decode(&self, value: String) -> String{
190        //
191        let mut char_vec = self.contrary_mapping(value, false);
192        let mut binary_vec: Vec<Vec<i32>> = Vec::new();
193        let mut binary_vec_vec: Vec<Vec<i32>> = Vec::new();
194        let mut pad_number: Vec<i32> = Vec::new();
195        for i in char_vec{
196            if i == 65 as i32{
197                pad_number.push(1);
198            }
199            let chars = self.dec2binary(i, 6);
200            binary_vec.push(chars);
201        }
202        for i in pad_number{
203            binary_vec.pop();
204        }
205        let binary_eight = self.binary_split(binary_vec, 8);
206        let original_vec = self.binary2dec(binary_eight, 2);
207        let original_result = String::from_utf8(original_vec);
208        let original = match original_result {
209            Ok(res) => res,
210            Err(err) => {
211                println!("Error: vec trans to String error.");
212                "".to_string()
213            }
214        };
215        original
216    }
217
218    pub fn decode_url(&self, value: String) -> String{
219        //
220        let mut char_vec = self.contrary_mapping(value, true);
221        let mut binary_vec: Vec<Vec<i32>> = Vec::new();
222        let mut binary_vec_vec: Vec<Vec<i32>> = Vec::new();
223        let mut pad_number: Vec<i32> = Vec::new();
224        for i in char_vec{
225            if i == 65 as i32{
226                pad_number.push(1);
227            }
228            let chars = self.dec2binary(i, 6);
229            binary_vec.push(chars);
230        }
231        for i in pad_number{
232            binary_vec.pop();
233        }
234        let binary_eight = self.binary_split(binary_vec, 8);
235        let original_vec = self.binary2dec(binary_eight, 2);
236        let original_result = String::from_utf8(original_vec);
237        let original = match original_result {
238            Ok(res) => res,
239            Err(err) => {
240                println!("Error: vec trans to String error.");
241                "".to_string()
242            }
243        };
244        original
245    }
246
247    fn contrary_mapping(&self, value: String, url: bool) -> Vec<i32>{
248        // Mapping, String trans to vec
249        let mut standard = self.standard_code_contrary();
250        if url{
251            standard = self.standard_code_contrary_url();
252        }
253        let mut standard_code_vec: Vec<i32> = Vec::new();
254        for i in value.chars(){
255            let res = match standard.get(&i) {
256                Some(r) => *r,
257                None => 10000
258            };
259            standard_code_vec.push(res);
260        }
261        standard_code_vec
262    }
263
264    fn binary_trans(&self, value: &[u8], url: bool) -> Vec<char>{
265        //
266        let mut binary_all_vec: Vec<Vec<i32>> = Vec::new();
267        for i in value{
268            let binary_sign_vec = self.dec2binary(*i as i32, 8);
269            binary_all_vec.push(binary_sign_vec);
270        }
271        let (binary_full, padding_number) = self.padding(binary_all_vec);
272        let binary_six = self.binary_split(binary_full,  6);
273        let base64_code = self.binary2dec(binary_six, padding_number);
274        let base_encode_value = self.mapping(base64_code, url);
275        base_encode_value
276    }
277
278    fn dec2binary(&self, value: i32, number: i32) -> Vec<i32>{
279        // ASCII value to binary
280        let mut binary: Vec<i32> = Vec::new();
281        let mut val = value;
282        for i in 0..number{
283            let result = self.mods(&mut val) as i32;
284            // 如果有余数就减1,取除以2的商作为下一次取余的被除数。Python中可用地板除
285            if result == 1{
286                val = (val -1) / 2;
287            }else{
288                val = val / 2;
289            }
290            binary.push(result);
291        }
292        binary.reverse();
293        binary
294    }
295
296    fn mods(&self, value: &mut i32) -> i32{
297        // mods for desc to binary, so % 2
298        *value % 2
299    }
300
301    fn padding(&self, mut value: Vec<Vec<i32>>) -> (Vec<Vec<i32>>, i32){
302        // 不足24则补0
303        let mut length: i32 = 0;
304        for i in 0..value.len(){
305            length += value[i].len() as i32;
306        }
307        let remainder = length % 24;
308        if remainder > 0{
309            for i in 0..24 - remainder{
310                value.push(vec![0]);
311            }
312        }
313
314        // 是否补0会影响后续计算
315        if remainder == 0{
316            return (value, remainder)
317        }else{
318            return (value, 24 - remainder)
319        }
320
321    }
322
323    fn binary_split(&self, value: Vec<Vec<i32>>, number: usize) -> Vec<String>{
324        // Split the binary, before number trans to after number
325        // [[1, 1, 1, 0, 0, 1], [0, 0, 1, 0, 1, 1], [1, 1, 0, 1, 1, 0]]
326        let mut value_string = String::from("");
327        for vec32 in value.iter(){
328            for v in vec32{
329                value_string.push_str(&v.to_string());
330            }
331        }
332        let mut binary_vec: Vec<String> = Vec::new();
333        let group_number = value_string.len() / number; // 72/8 or 72/6
334        for i in 1..group_number + 1{
335            binary_vec.push(value_string[(i-1)*number..i*number].to_string());
336        }
337        binary_vec
338    }
339
340    fn binary2dec(&self, value: Vec<String>, padding_number: i32) -> Vec<u8>{
341        // binary trans to desc
342        let mut pad_number = padding_number / 8; // 根据补0数计算补位数
343        // String trans to Vec<i32>, because String can not slice or sort.
344        let mut binary_six_vec: Vec<Vec<i32>> = Vec::new();
345        for binary in value{
346            let mut six_vec: Vec<i32> = Vec::new();
347            // String can not for,but String.chars() or String.bytes() can for
348            for i in binary.chars(){
349                let mut x: i32 = 0;
350                if i == '1'{
351                    x = 1;
352                }
353                six_vec.push(x);
354            }
355            binary_six_vec.push(six_vec);
356        }
357
358        // algorithm for binary 011000 trans to desc:
359        // 0*2.pow(5)+1*2.pow(4)+1*2.pow(3)+0*2.pow(2)+0*2.pow(1)
360        const BINARY: i32 = 2;
361        let mut desc_vec: Vec<u8> = Vec::new();
362        for six_vec in 0..binary_six_vec.len(){
363            binary_six_vec[six_vec].reverse(); // 按照计算公式,此处需要反序
364            let mut desc = 0;
365            for i in 0..binary_six_vec[six_vec].len(){
366                desc += binary_six_vec[six_vec][i] * BINARY.pow(i as u32);
367            }
368            desc_vec.push(desc as u8);
369        }
370
371        // Make up according to the number of padding number
372        for i in 0..pad_number{
373            desc_vec.pop();
374        }
375        for i in 0..pad_number{
376            desc_vec.push(65);
377        }
378        desc_vec
379    }
380
381    fn mapping(&self, numbers: Vec<u8>, url: bool) -> Vec<char>{
382        // return the base64 mapping result Vec<char>
383        let mut base64_encode: Vec<char> = Vec::new();
384
385        // choose the standard code
386        let mut standard_code = self.standard_code();
387        if url{
388            standard_code = self.standard_code_url();
389        }
390        for i in numbers{
391            let x = i as i32;
392            let chars = standard_code.get(&x);
393            let res = match chars {
394                Some(v) => v,
395                None => &'|'
396            };
397            base64_encode.push(*res);
398        }
399        base64_encode
400    }
401
402}