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}