ps_base64/decoder/
mod.rs

1pub mod map;
2
3pub use map::*;
4
5#[inline]
6pub(crate) const fn align_up(size: usize) -> usize {
7    (size + 3) & !3
8}
9
10#[inline]
11pub(crate) const fn three_fourths(size: usize) -> usize {
12    (size * 3).div_ceil(4)
13}
14
15#[must_use]
16pub fn decode(input: &[u8]) -> Vec<u8> {
17    let mut output: Vec<u8> = Vec::with_capacity(align_up(three_fourths(input.len())));
18
19    let mut iterator = input
20        .iter()
21        .copied()
22        .filter(|&byte| !byte.is_ascii_whitespace() && byte != b'=');
23
24    loop {
25        let mut value = 0;
26
27        if let Some(b) = iterator.next() {
28            value |= u32::from(DECODE_MAP[usize::from(b)]) << 18;
29        } else {
30            break;
31        }
32
33        if let Some(b) = iterator.next() {
34            value |= u32::from(DECODE_MAP[usize::from(b)]) << 12;
35        } else {
36            output.push(value.to_be_bytes()[1]);
37            break;
38        }
39
40        if let Some(b) = iterator.next() {
41            value |= u32::from(DECODE_MAP[usize::from(b)]) << 6;
42        } else {
43            let bytes = value.to_be_bytes();
44
45            output.push(bytes[1]);
46
47            if bytes[2] != 0 {
48                output.push(bytes[2]);
49            }
50
51            break;
52        }
53
54        if let Some(b) = iterator.next() {
55            value |= u32::from(DECODE_MAP[usize::from(b)]);
56        } else {
57            let bytes = value.to_be_bytes();
58
59            output.push(bytes[1]);
60            output.push(bytes[2]);
61
62            if bytes[3] != 0 {
63                output.push(bytes[3]);
64            }
65
66            break;
67        }
68
69        output.extend_from_slice(&value.to_be_bytes()[1..]);
70    }
71
72    output
73}
74
75#[must_use]
76pub fn sized_decode<const S: usize>(input: &[u8]) -> [u8; S] {
77    let mut output = [0u8; S];
78    let mut iterator = input
79        .iter()
80        .copied()
81        .filter(|&byte| !byte.is_ascii_whitespace() && byte != b'=');
82    let mut decoded_bytes = 0;
83
84    loop {
85        let mut value = 0;
86
87        if decoded_bytes >= S {
88            break;
89        }
90
91        if let Some(b) = iterator.next() {
92            value |= u32::from(DECODE_MAP[usize::from(b)]) << 18;
93        } else {
94            break;
95        }
96
97        if let Some(b) = iterator.next() {
98            value |= u32::from(DECODE_MAP[usize::from(b)]) << 12;
99        } else {
100            output[decoded_bytes] = value.to_be_bytes()[1];
101            break;
102        }
103
104        if decoded_bytes + 1 >= S {
105            let bytes = value.to_be_bytes();
106            output[decoded_bytes] = bytes[1];
107            break;
108        }
109
110        if let Some(b) = iterator.next() {
111            value |= u32::from(DECODE_MAP[usize::from(b)]) << 6;
112        } else {
113            let bytes = value.to_be_bytes();
114            output[decoded_bytes] = bytes[1];
115            output[decoded_bytes + 1] = bytes[2];
116            break;
117        }
118
119        if decoded_bytes + 2 >= S {
120            let bytes = value.to_be_bytes();
121            output[decoded_bytes] = bytes[1];
122            output[decoded_bytes + 1] = bytes[2];
123            break;
124        }
125
126        if let Some(b) = iterator.next() {
127            value |= u32::from(DECODE_MAP[usize::from(b)]);
128        } else {
129            let bytes = value.to_be_bytes();
130            output[decoded_bytes] = bytes[1];
131            output[decoded_bytes + 1] = bytes[2];
132            output[decoded_bytes + 2] = bytes[3];
133            break;
134        }
135
136        let bytes = value.to_be_bytes();
137
138        output[decoded_bytes..decoded_bytes + 3].copy_from_slice(&bytes[1..]);
139
140        decoded_bytes += 3;
141    }
142    output
143}