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