Skip to main content

base64_const/
macros.rs

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}