mini_rcrypt/
base64.rs

1use crate::{
2    utils::{char64, get_byte_from_char, get_byte_from_number},
3    BASE64_CODE,
4};
5
6pub fn encode_base64<'a>(value: Vec<isize>, len: usize) -> Result<String, &'a str> {
7    if len <= 0 || len > value.len() {
8        return Err("Invalid len");
9    }
10
11    let mut off = 0;
12
13    let mut rs = String::new();
14
15    let mut c1;
16    let mut c2;
17
18    while off < len {
19        c1 = value[off] & 0xff;
20        off += 1;
21
22        rs.push(BASE64_CODE[(c1 as usize >> 2) & 0x3f]);
23
24        c1 = (c1 & 0x03) << 4;
25
26        if off >= len {
27            rs.push(BASE64_CODE[c1 as usize & 0x3f]);
28
29            break;
30        }
31
32        c2 = value[off] & 0xff;
33        c1 |= (c2 >> 4) & 0x0f;
34        off += 1;
35
36        rs.push(BASE64_CODE[c1 as usize & 0x3f]);
37
38        c1 = (c2 & 0x0f) << 2;
39
40        if off >= len {
41            rs.push(BASE64_CODE[c1 as usize & 0x3f]);
42
43            break;
44        }
45
46        c2 = value[off] & 0xff;
47        c1 |= (c2 >> 6) & 0x03;
48        off += 1;
49
50        rs.push(BASE64_CODE[c1 as usize & 0x3f]);
51        rs.push(BASE64_CODE[c2 as usize & 0x3f]);
52    }
53
54    Ok(rs)
55}
56
57pub fn decode_base64<'a>(s: String, maxlen: usize) -> Result<Vec<isize>, &'a str> {
58    if maxlen <= 0 {
59        return Err("Invalid maxlen");
60    }
61
62    let mut rs = String::new();
63    let mut off = 0;
64    let slen = s.len();
65    let mut olen = 0;
66
67    let mut c1;
68    let mut c2;
69    let mut c3;
70    let mut c4;
71    let mut o;
72
73    while off < slen - 1 && olen < maxlen {
74        match s.chars().nth(off) {
75            Some(x) => c1 = char64(x),
76            None => {
77                let err = format!("Invalid input: {}", s);
78
79                return Err(Box::leak(err.into_boxed_str()));
80            }
81        }
82        off += 1;
83
84        match s.chars().nth(off) {
85            Some(x) => c2 = char64(x),
86            None => {
87                let err = format!("Invalid input: {}", s);
88
89                return Err(Box::leak(err.into_boxed_str()));
90            }
91        }
92        off += 1;
93
94        if c1 == -1 || c2 == -1 {
95            break;
96        }
97
98        o = get_byte_from_number(c1 << 2);
99        o |= (c2 & 0x30) >> 4;
100
101        match char::from_u32(o as u8 as u32) {
102            Some(x) => rs.push(x),
103            None => {
104                let err = format!("Invalid byte: {}", o);
105
106                return Err(Box::leak(err.into_boxed_str()));
107            }
108        }
109
110        olen += 1;
111        if olen >= maxlen || off >= slen {
112            break;
113        }
114
115        match s.chars().nth(off) {
116            Some(x) => c3 = char64(x),
117            None => {
118                let err = format!("Invalid input: {}", s);
119
120                return Err(Box::leak(err.into_boxed_str()));
121            }
122        }
123        off += 1;
124
125        if c3 == -1 {
126            break;
127        }
128
129        o = get_byte_from_number((c2 & 0x0f) << 4);
130        o |= (c3 & 0x3c) >> 2;
131
132        match char::from_u32(o as u8 as u32) {
133            Some(x) => rs.push(x),
134            None => {
135                let err = format!("Invalid byte: {}", o);
136
137                return Err(Box::leak(err.into_boxed_str()));
138            }
139        }
140
141        olen += 1;
142        if olen >= maxlen || off >= slen {
143            break;
144        }
145
146        match s.chars().nth(off) {
147            Some(x) => c4 = char64(x),
148            None => {
149                let err = format!("Invalid input: {}", s);
150
151                return Err(Box::leak(err.into_boxed_str()));
152            }
153        }
154        off += 1;
155
156        o = get_byte_from_number((c3 & 0x03) << 6);
157        o |= c4;
158
159        match char::from_u32(o as u8 as u32) {
160            Some(x) => rs.push(x),
161            None => {
162                let err = format!("Invalid byte: {}", o);
163
164                return Err(Box::leak(err.into_boxed_str()));
165            }
166        }
167
168        olen += 1;
169    }
170
171    let mut ret: Vec<isize> = Vec::new();
172
173    off = 0;
174
175    while off < olen {
176        match rs.chars().nth(off) {
177            Some(x) => ret.push(get_byte_from_char(x)),
178            None => {
179                let err = format!("Invalid result: {}", rs);
180
181                return Err(Box::leak(err.into_boxed_str()));
182            }
183        }
184
185        off += 1;
186    }
187
188    Ok(ret)
189}