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}