ps_base64/encoder/
mod.rs

1pub const ALPHABET: &[u8; 64] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789~_";
2
3#[inline]
4#[must_use]
5pub fn sized_encode<const S: usize>(input: &[u8]) -> [u8; S] {
6    let mut output = [b'='; S];
7    let mut index = 0;
8
9    let mut push = |byte: u8| {
10        if index < S {
11            output[index] = byte;
12            index += 1;
13        }
14    };
15
16    for chunk in input.chunks_exact(3) {
17        push(ALPHABET[(chunk[0] >> 2) as usize]);
18        push(ALPHABET[(((chunk[0] & 0x3) << 4) | (chunk[1] >> 4)) as usize]);
19        push(ALPHABET[(((chunk[1] & 0xf) << 2) | (chunk[2] >> 6)) as usize]);
20        push(ALPHABET[(chunk[2] & 0x3f) as usize]);
21    }
22
23    let remainder = input.len() % 3;
24
25    if remainder == 1 {
26        let index: usize = input.len() - 1;
27
28        push(ALPHABET[(input[index] >> 2) as usize]);
29        push(ALPHABET[((input[index] & 3) << 4) as usize]);
30    } else if remainder == 2 {
31        let index: usize = input.len() - 2;
32
33        push(ALPHABET[(input[index] >> 2) as usize]);
34        push(ALPHABET[(((input[index] & 0x3) << 4) | (input[index + 1] >> 4)) as usize]);
35        push(ALPHABET[((input[index + 1] & 0xf) << 2) as usize]);
36    }
37
38    output
39}
40
41#[must_use]
42pub fn encode(input: &[u8]) -> String {
43    let mut output = Vec::with_capacity(input.len() * 4 / 3 + 1);
44
45    for chunk in input.chunks_exact(3) {
46        output.push(ALPHABET[(chunk[0] >> 2) as usize]);
47        output.push(ALPHABET[(((chunk[0] & 0x3) << 4) | (chunk[1] >> 4)) as usize]);
48        output.push(ALPHABET[(((chunk[1] & 0xf) << 2) | (chunk[2] >> 6)) as usize]);
49        output.push(ALPHABET[(chunk[2] & 0x3f) as usize]);
50    }
51
52    let remainder = input.len() % 3;
53
54    if remainder == 1 {
55        let index: usize = input.len() - 1;
56
57        output.push(ALPHABET[(input[index] >> 2) as usize]);
58        output.push(ALPHABET[((input[index] & 3) << 4) as usize]);
59    } else if remainder == 2 {
60        let index: usize = input.len() - 2;
61
62        output.push(ALPHABET[(input[index] >> 2) as usize]);
63        output.push(ALPHABET[(((input[index] & 0x3) << 4) | (input[index + 1] >> 4)) as usize]);
64        output.push(ALPHABET[((input[index + 1] & 0xf) << 2) as usize]);
65    }
66
67    // ALPHABET does not contain invalid utf8 chars
68    unsafe { String::from_utf8_unchecked(output) }
69}