rust_web_server/core/base64/
mod.rs1use std::collections::HashMap;
6use crate::symbol::SYMBOL;
7
8mod decode;
9pub use decode::{Alphabet, DecodeError, Decoder};
10
11#[cfg(test)]
12mod tests;
13
14const STANDARD_CHARS: &[u8; 64] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
15
16fn encode_standard(bytes: &[u8]) -> String {
18 let mut out = Vec::with_capacity(bytes.len().div_ceil(3) * 4);
19 let (chunks, remainder) = bytes.as_chunks::<3>();
20 for c in chunks {
21 let n = (c[0] as usize) << 16 | (c[1] as usize) << 8 | c[2] as usize;
22 out.extend_from_slice(&[STANDARD_CHARS[n >> 18], STANDARD_CHARS[n >> 12 & 63], STANDARD_CHARS[n >> 6 & 63], STANDARD_CHARS[n & 63]]);
23 }
24 match *remainder {
25 [a] => {
26 let n = (a as usize) << 16;
27 out.extend_from_slice(&[STANDARD_CHARS[n >> 18], STANDARD_CHARS[n >> 12 & 63], b'=', b'=']);
28 }
29 [a, b] => {
30 let n = (a as usize) << 16 | (b as usize) << 8;
31 out.extend_from_slice(&[STANDARD_CHARS[n >> 18], STANDARD_CHARS[n >> 12 & 63], STANDARD_CHARS[n >> 6 & 63], b'=']);
32 }
33 _ => {}
34 }
35 String::from_utf8(out).unwrap_or_default()
37}
38
39pub struct Base64;
40
41impl Base64 {
42
43 pub fn encode(bytes: &[u8]) -> Result<String, String> {
46 Ok(encode_standard(bytes))
47 }
48
49 pub fn decode(text: String) -> Result<Vec<u8>, String> {
52 Ok(Decoder::STANDARD.decode(text.as_bytes())?)
53 }
54
55 pub fn decode_sequence(text: String) -> Result<Vec<u8>, String> {
56 let result : Vec<u8> = vec![];
57
58 let number_of_equal_signs = text.matches(SYMBOL.equals).count();
59
60 if number_of_equal_signs == 2 {
61 let boxed_first_byte = text.chars().nth(0);
62 if boxed_first_byte.is_none() {
63 return Err("unexpected error, unable to get char at position 0".to_string());
64 }
65 let first_byte = boxed_first_byte.unwrap() as u8;
66 let _first_byte_as_string = format!("{first_byte:b}");
67
68 let boxed_conversion = Base64::convert_base64_char_to_number(first_byte as char);
69 if boxed_conversion.is_err() {
70 let message = boxed_conversion.err().unwrap();
71 return Err(message);
72 }
73 let converted_first_byte = boxed_conversion.unwrap();
74 let shifted_converted_first_byte = converted_first_byte << 2;
75 let _shifted_converted_first_byte_as_string = format!("{converted_first_byte:b}");
76
77
78
79 let boxed_second_byte = text.chars().nth(1);
80 if boxed_second_byte.is_none() {
81 return Err("unexpected error, unable to get char at position 0".to_string());
82 }
83 let second_byte = boxed_second_byte.unwrap() as u8;
84 let _second_byte_as_string = format!("{second_byte:b}");
85
86
87 let boxed_conversion = Base64::convert_base64_char_to_number(second_byte as char);
88 if boxed_conversion.is_err() {
89 let message = boxed_conversion.err().unwrap();
90 return Err(message);
91 }
92 let converted_second_byte = boxed_conversion.unwrap();
93
94
95 let shifted_converted_second_byte = converted_second_byte >> 4;
96 let _shifted_second_byte_as_string = format!("{shifted_converted_second_byte:b}");
97
98
99 let resulted_byte = shifted_converted_first_byte | shifted_converted_second_byte;
100 return Ok(vec![resulted_byte]);
101
102 }
103
104 if number_of_equal_signs == 1 {
105 let boxed_first_byte = text.chars().nth(0);
106 if boxed_first_byte.is_none() {
107 return Err("unexpected error, unable to get char at position 0".to_string());
108 }
109 let first_byte = boxed_first_byte.unwrap() as u8;
110 let _first_byte_as_string = format!("{first_byte:b}");
111
112 let boxed_conversion = Base64::convert_base64_char_to_number(first_byte as char);
113 if boxed_conversion.is_err() {
114 let message = boxed_conversion.err().unwrap();
115 return Err(message);
116 }
117 let converted_first_byte = boxed_conversion.unwrap();
118 let shifted_converted_first_byte = converted_first_byte << 2;
119 let _shifted_converted_first_byte_as_string = format!("{converted_first_byte:b}");
120
121
122
123 let boxed_second_byte = text.chars().nth(1);
124 if boxed_second_byte.is_none() {
125 return Err("unexpected error, unable to get char at position 1".to_string());
126 }
127 let second_byte = boxed_second_byte.unwrap() as u8;
128 let _second_byte_as_string = format!("{second_byte:b}");
129
130
131 let boxed_conversion = Base64::convert_base64_char_to_number(second_byte as char);
132 if boxed_conversion.is_err() {
133 let message = boxed_conversion.err().unwrap();
134 return Err(message);
135 }
136 let converted_second_byte = boxed_conversion.unwrap();
137
138
139 let shifted_converted_second_byte = converted_second_byte >> 4;
140 let _shifted_second_byte_as_string = format!("{shifted_converted_second_byte:b}");
141
142
143 let first_char_as_byte = shifted_converted_first_byte | shifted_converted_second_byte;
144
145
146
147
148 let second_char_part_one = (converted_second_byte & 0b00001111) << 4;
150 let boxed_third_byte = text.chars().nth(2);
151 if boxed_third_byte.is_none() {
152 return Err("unexpected error, unable to get char at position 2".to_string());
153 }
154 let third_byte = boxed_third_byte.unwrap() as u8;
155
156 let boxed_conversion = Base64::convert_base64_char_to_number(third_byte as char);
157 if boxed_conversion.is_err() {
158 let message = boxed_conversion.err().unwrap();
159 return Err(message);
160 }
161 let converted_third_byte = boxed_conversion.unwrap();
162 let shifted_third_byte = (0b00111100 & converted_third_byte) >> 2;
163
164 let second_char_as_byte = shifted_third_byte | second_char_part_one;
165
166 return Ok(vec![first_char_as_byte, second_char_as_byte]);
167
168 }
169
170 if number_of_equal_signs == 0 {
171 let boxed_first_byte = text.chars().nth(0);
172 if boxed_first_byte.is_none() {
173 return Err("unexpected error, unable to get char at position 0".to_string());
174 }
175 let first_byte = boxed_first_byte.unwrap() as u8;
176 let _first_byte_as_string = format!("{first_byte:b}");
177
178 let boxed_conversion = Base64::convert_base64_char_to_number(first_byte as char);
179 if boxed_conversion.is_err() {
180 let message = boxed_conversion.err().unwrap();
181 return Err(message);
182 }
183 let converted_first_byte = boxed_conversion.unwrap();
184 let shifted_converted_first_byte = converted_first_byte << 2;
185 let _shifted_converted_first_byte_as_string = format!("{converted_first_byte:b}");
186
187
188
189 let boxed_second_byte = text.chars().nth(1);
190 if boxed_second_byte.is_none() {
191 return Err("unexpected error, unable to get char at position 1".to_string());
192 }
193 let second_byte = boxed_second_byte.unwrap() as u8;
194 let _second_byte_as_string = format!("{second_byte:b}");
195
196 let boxed_conversion = Base64::convert_base64_char_to_number(second_byte as char);
197 if boxed_conversion.is_err() {
198 let message = boxed_conversion.err().unwrap();
199 return Err(message);
200 }
201 let converted_second_byte = boxed_conversion.unwrap();
202
203
204 let shifted_converted_second_byte = converted_second_byte >> 4;
205 let _shifted_second_byte_as_string = format!("{shifted_converted_second_byte:b}");
206
207
208 let first_char_as_byte = shifted_converted_first_byte | shifted_converted_second_byte;
209
210
211
212
213 let second_char_part_one = (converted_second_byte & 0b00001111) << 4;
215 let boxed_third_byte = text.chars().nth(2);
216 if boxed_third_byte.is_none() {
217 return Err("unexpected error, unable to get char at position 2".to_string());
218 }
219 let third_byte = boxed_third_byte.unwrap() as u8;
220
221 let boxed_conversion = Base64::convert_base64_char_to_number(third_byte as char);
222 if boxed_conversion.is_err() {
223 let message = boxed_conversion.err().unwrap();
224 return Err(message);
225 }
226 let converted_third_byte = boxed_conversion.unwrap();
227 let shifted_third_byte = (0b00111100 & converted_third_byte) >> 2;
228
229 let second_char_as_byte = shifted_third_byte | second_char_part_one;
230
231 let boxed_conversion = Base64::convert_base64_char_to_number(third_byte as char);
232 if boxed_conversion.is_err() {
233 let message = boxed_conversion.err().unwrap();
234 return Err(message);
235 }
236 let converted_third_byte = boxed_conversion.unwrap();
237 let masked_third_byte = converted_third_byte & 0b00000011;
238 let shifted_masked_third_byte = masked_third_byte << 6;
239
240
241 let boxed_fourth_byte = text.chars().nth(3);
242 if boxed_fourth_byte.is_none() {
243 return Err("unexpected error, unable to get char at position 3".to_string());
244 }
245 let fourth_byte = boxed_fourth_byte.unwrap() as u8;
246
247 let boxed_conversion = Base64::convert_base64_char_to_number(fourth_byte as char);
248 if boxed_conversion.is_err() {
249 let message = boxed_conversion.err().unwrap();
250 return Err(message);
251 }
252 let converted_fourth_byte = boxed_conversion.unwrap();
253 let masked_fourth_byte = converted_fourth_byte & 0b00111111;
254
255 let third_char_as_byte = shifted_masked_third_byte | masked_fourth_byte;
256
257
258 return Ok(vec![first_char_as_byte, second_char_as_byte, third_char_as_byte]);
259
260 }
261
262 Ok(result)
263 }
264
265 pub fn encode_sequence(bytes: &[u8]) -> Result<String, String> {
266 if bytes.len() > 3 {
267 return Err("sequence encodes at most 3 bytes at once".to_string());
268 }
269
270 if bytes.len() == 0 {
271 return Err("sequence encodes at least 1 byte".to_string());
272 }
273
274 if bytes.len() == 1 {
275 let boxed_byte = bytes.get(0);
276 if boxed_byte.is_none() {
277 return Err("byte at pos 1 is empty".to_string());
278 }
279
280 let byte = boxed_byte.unwrap();
281 let _byte_as_string = format!("{byte:b}");
282 let shifted_first_sextet = byte >> 2;
283 let _shifted_first_sextet_as_string = format!("{shifted_first_sextet:b}");
284
285 let shifted_second_sextet = (byte & 0b00000011) << 4;
286 let _shifted_first_sextet_as_string = format!("{shifted_second_sextet:b}");
287
288 let mut result_buffer: Vec<String> = vec![];
289
290 let boxed_encoded_char = Base64::convert_number_to_base64_char(shifted_first_sextet);
291 if boxed_encoded_char.is_err() {
292 return Err(boxed_encoded_char.err().unwrap());
293 }
294
295 result_buffer.push(boxed_encoded_char.unwrap().to_string());
296
297 let boxed_encoded_char = Base64::convert_number_to_base64_char(shifted_second_sextet);
298 if boxed_encoded_char.is_err() {
299 return Err(boxed_encoded_char.err().unwrap());
300 }
301
302 result_buffer.push(boxed_encoded_char.unwrap().to_string());
303
304 result_buffer.push(SYMBOL.equals.to_string());
305 result_buffer.push(SYMBOL.equals.to_string());
306
307 let result : String = result_buffer.join(SYMBOL.empty_string);
308 return Ok(result);
309 }
310
311 if bytes.len() == 2 {
312 let boxed_byte = bytes.get(0);
313 if boxed_byte.is_none() {
314 return Err("byte at pos 1 is empty".to_string());
315 }
316
317 let byte = boxed_byte.unwrap();
318 let _byte_as_string = format!("{byte:b}");
319 let shifted_first_sextet = byte >> 2;
320 let _shifted_first_sextet_as_string = format!("{shifted_first_sextet:b}");
321
322
323
324 let mut result_buffer: Vec<String> = vec![];
325
326 let boxed_encoded_char = Base64::convert_number_to_base64_char(shifted_first_sextet);
327 if boxed_encoded_char.is_err() {
328 return Err(boxed_encoded_char.err().unwrap());
329 }
330
331 let char : String = boxed_encoded_char.unwrap().to_string();
332 result_buffer.push(char);
333
334
335 let shifted_second_sextet_part_one = (byte & 0b00000011) << 4;
337 let _shifted_second_sextet_as_string = format!("{shifted_second_sextet_part_one:b}");
338
339
340 let boxed_byte = bytes.get(1);
342 if boxed_byte.is_none() {
343 return Err("byte at pos 1 is empty".to_string());
344 }
345
346 let second_byte = boxed_byte.unwrap();
347 let shifted_second_byte_part_two = second_byte >> 4;
348
349
350 let second_sextet = shifted_second_sextet_part_one | shifted_second_byte_part_two;
351 let boxed_second_encoded_char = Base64::convert_number_to_base64_char(second_sextet);
352 if boxed_second_encoded_char.is_err() {
353 return Err(boxed_second_encoded_char.err().unwrap());
354 }
355
356 let char = boxed_second_encoded_char.unwrap();
357 result_buffer.push(char.to_string());
358
359
360 let base64_third_char = (second_byte & 0b00001111) << 2;
362 let boxed_third_encoded_char = Base64::convert_number_to_base64_char(base64_third_char);
363 if boxed_third_encoded_char.is_err() {
364 return Err(boxed_third_encoded_char.err().unwrap());
365 }
366 let char = boxed_third_encoded_char.unwrap();
367 result_buffer.push(char.to_string());
368
369
370
371 result_buffer.push(SYMBOL.equals.to_string());
372
373 let result : String = result_buffer.join(SYMBOL.empty_string);
374 return Ok(result);
375 }
376
377 if bytes.len() == 3 {
378 let boxed_byte = bytes.get(0);
379 if boxed_byte.is_none() {
380 return Err("byte at pos 1 is empty".to_string());
381 }
382
383 let byte = boxed_byte.unwrap();
384 let _byte_as_string = format!("{byte:b}");
385 let shifted_first_sextet = byte >> 2;
386 let _shifted_first_sextet_as_string = format!("{shifted_first_sextet:b}");
387
388
389
390 let mut result_buffer: Vec<String> = vec![];
391
392 let boxed_encoded_char = Base64::convert_number_to_base64_char(shifted_first_sextet);
393 if boxed_encoded_char.is_err() {
394 return Err(boxed_encoded_char.err().unwrap());
395 }
396
397 let char : String = boxed_encoded_char.unwrap().to_string();
398 result_buffer.push(char);
399
400
401 let shifted_second_sextet_part_one = (byte & 0b00000011) << 4;
403 let _shifted_second_sextet_as_string = format!("{shifted_second_sextet_part_one:b}");
404
405
406 let boxed_byte = bytes.get(1);
408 if boxed_byte.is_none() {
409 return Err("byte at pos 1 is empty".to_string());
410 }
411
412 let second_byte = boxed_byte.unwrap();
413 let shifted_second_byte_part_two = second_byte >> 4;
414
415
416 let second_sextet = shifted_second_sextet_part_one | shifted_second_byte_part_two;
417 let boxed_second_encoded_char = Base64::convert_number_to_base64_char(second_sextet);
418 if boxed_second_encoded_char.is_err() {
419 return Err(boxed_second_encoded_char.err().unwrap());
420 }
421
422 let char = boxed_second_encoded_char.unwrap();
423 result_buffer.push(char.to_string());
424
425
426 let base64_third_char = (second_byte & 0b00001111) << 2;
428
429
430 let boxed_byte = bytes.get(2);
431 if boxed_byte.is_none() {
432 return Err("byte at pos 1 is empty".to_string());
433 }
434
435 let third_byte = boxed_byte.unwrap();
436 let third_encoded_char_part2 = (third_byte & 0b11000000) >> 6;
437
438 let third_encoded_char = base64_third_char | third_encoded_char_part2;
439
440 let boxed_third_encoded_char = Base64::convert_number_to_base64_char(third_encoded_char);
441 if boxed_third_encoded_char.is_err() {
442 return Err(boxed_third_encoded_char.err().unwrap());
443 }
444 let char = boxed_third_encoded_char.unwrap();
445 result_buffer.push(char.to_string());
446
447 let fourth_encoded_char = third_byte & 0b00111111;
448 let boxed_fourth_encoded_char = Base64::convert_number_to_base64_char(fourth_encoded_char);
449 if boxed_fourth_encoded_char.is_err() {
450 return Err(boxed_fourth_encoded_char.err().unwrap());
451 }
452 let char = boxed_fourth_encoded_char.unwrap();
453 result_buffer.push(char.to_string());
454
455 let result : String = result_buffer.join(SYMBOL.empty_string);
456 return Ok(result);
457 }
458
459 Ok("".to_string())
460 }
461
462 pub fn convert_base64_char_to_number(char: char) -> Result<u8, String> {
463 let base64_char_list : Vec<char> = Base64::get_base64_char_list();
464 let mut map : HashMap<char, u8> = HashMap::new();
465
466 for (index, char) in base64_char_list.iter().enumerate() {
467 map.insert(*char, index as u8);
468 }
469
470 let boxed_get = map.get(&char);
471 if boxed_get.is_none() {
472 let message = format!("unable to get char number: {}", char);
473 return Err(message);
474 }
475 let index : &u8 = map.get(&char).unwrap();
476
477 Ok(*index)
478 }
479
480 pub fn get_base64_char_list() -> Vec<char> {
481 let mut base64_table : Vec<char> = vec![];
482
483 let mut uppercase = ('A'..='Z').into_iter().collect::<Vec<char>>();
484 base64_table.append(&mut uppercase);
485
486 let mut lowercase = ('a'..='z').into_iter().collect::<Vec<char>>();
487 base64_table.append(&mut lowercase);
488
489 let mut numbers = ('0'..='9').into_iter().collect::<Vec<char>>();
490 base64_table.append(&mut numbers);
491
492 base64_table.push('+');
493 base64_table.push('/');
494
495 base64_table
496 }
497
498 pub fn convert_number_to_base64_char(number: u8) -> Result<char, String> {
499 if number > 63 {
500 return Err("number exceeds range 0 - 63".to_string());
501 }
502
503 let base64_table : Vec<char> = Base64::get_base64_char_list();
504
505 let boxed_get : Option<char> = base64_table.get(number as usize).copied();
506 if boxed_get.is_none() {
507 return Err(format!("unable to convert number to base64 char: {}", number).to_string())
508 }
509
510 let char: char = boxed_get.unwrap();
511 Ok(char)
512 }
513}