1#[macro_export]
2macro_rules! base64_decode {
3 ($base64:expr) => {{
4 const INPUT: &str = $base64;
5 const BYTES: &[u8] = INPUT.as_bytes();
6 const LEN: usize = {
7 let mut index = 0;
8 let mut start_bit: u8 = 0;
9 let mut result_idx = 0;
10
11 while index < BYTES.len() {
12 let ascii = BYTES[index];
13 if ascii == b'=' {
14 break;
15 }
16
17 if start_bit >= 2 {
18 result_idx += 1;
19 }
20 start_bit = (start_bit + 6) % 8;
21 index += 1;
22 }
23 result_idx
24 };
25 const DECODED: [u8; LEN] = {
26 let mut result = [0u8; LEN];
27 let mut index = 0;
28 let mut start_bit: u8 = 0;
29 let mut byte: u8 = 0;
30 let mut result_idx = 0;
31
32 while index < BYTES.len() && result_idx < LEN {
33 let ascii = BYTES[index];
34 if ascii == b'=' {
35 break;
36 }
37
38 let b64 = if ascii >= b'a' {
39 26 + ascii - b'a'
40 } else if ascii >= b'A' {
41 ascii - b'A'
42 } else if ascii >= b'0' {
43 52 + ascii - b'0'
44 } else if ascii == b'+' {
45 62
46 } else if ascii == b'/' {
47 63
48 } else {
49 0xff
50 };
51
52 if start_bit <= 2 {
53 byte |= b64 << (2 - start_bit);
54 if start_bit == 2 {
55 if result_idx < LEN {
56 result[result_idx] = byte;
57 result_idx += 1;
58 }
59 byte = 0;
60 }
61 } else {
62 byte |= b64 >> (start_bit - 2);
63 if result_idx < LEN {
64 result[result_idx] = byte;
65 result_idx += 1;
66 }
67 byte = b64 << (8 - start_bit + 2);
68 }
69 start_bit = (start_bit + 6) % 8;
70 index += 1;
71 }
72 result
73 };
74 DECODED
75 }};
76}
77
78#[macro_export]
79macro_rules! base64_url_unsafe {
80 ($base64:expr) => {{
81 const INPUT:&[u8] = $base64.as_bytes();
82 const SUFFIX_LEN:usize = 4 - (INPUT.len() % 4);
83 const LEN:usize = SUFFIX_LEN + INPUT.len();
84 const DECODED: [u8; LEN] = {
85 let mut index = 0;
86 let mut result = [0u8; LEN];
87 while index < INPUT.len() {
88 result[index] = match INPUT[index] {
89 b'-' => b'+',
90 b'_' => b'/',
91 c => c
92 };
93 index += 1;
94 }
95 let mut index = index;
96 while index < LEN {
97 result[index] = b'=';
98 index += 1;
99 }
100 result
101 };
102 std::str::from_utf8(&DECODED).unwrap()
103 }};
104}
105
106#[macro_export]
107macro_rules! base64_url_safe {
108 ($base64:expr) => {{
109 const INPUT:&[u8] = $base64.as_bytes();
110
111 const SUFFIX_LEN:usize = {
112 let mut suffix_len:usize = 0;
113 if INPUT.len() > 0 {
114 let mut index = INPUT.len() - 1;
115 while INPUT[index] == b'=' {
116 suffix_len += 1;
117 if index == 0 {break}
118 index -= 1;
119 }
120 }
121 suffix_len
122 };
123 const LEN:usize = INPUT.len() - SUFFIX_LEN;
124 const DECODED: [u8; LEN] = {
125 let mut index = 0;
126 let mut result = [0u8; LEN];
127 while index < LEN {
128 result[index] = match INPUT[index] {
129 b'+' => b'-',
130 b'/' => b'_',
131 c => c
132 };
133 index += 1;
134 }
135 result
136 };
137 std::str::from_utf8(&DECODED).unwrap()
138 }};
139}