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