1// Copyright (c) 2023 Huawei Device Co., Ltd.
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6//     http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14//! Base64 simple implementation.
15
16pub(crate) fn encode(input: &[u8]) -> Vec<u8> {
17    let mut output = Vec::new();
18
19    for chunk in input.chunks(3) {
20        output.push(BASE64_TABLE[((chunk[0] >> 2) & 0x3f) as usize]);
21        if chunk.len() == 3 {
22            output.push(BASE64_TABLE[(((chunk[0] & 0x3) << 4) | ((chunk[1] >> 4) & 0xf)) as usize]);
23            output.push(BASE64_TABLE[(((chunk[1] & 0xf) << 2) | ((chunk[2] >> 6) & 0x3)) as usize]);
24            output.push(BASE64_TABLE[(chunk[2] & 0x3f) as usize]);
25        } else if chunk.len() == 2 {
26            output.push(BASE64_TABLE[(((chunk[0] & 0x3) << 4) | ((chunk[1] >> 4) & 0xf)) as usize]);
27            output.push(BASE64_TABLE[((chunk[1] & 0xf) << 2) as usize]);
28            output.push(b'=');
29        } else if chunk.len() == 1 {
30            output.push(BASE64_TABLE[((chunk[0] & 0x3) << 4) as usize]);
31            output.push(b'=');
32            output.push(b'=');
33        }
34    }
35    output
36}
37
38static BASE64_TABLE: [u8; 64] = [
39    // 0     1     2     3     4     5     6     7
40    b'A', b'B', b'C', b'D', b'E', b'F', b'G', b'H', // 0
41    b'I', b'J', b'K', b'L', b'M', b'N', b'O', b'P', // 1
42    b'Q', b'R', b'S', b'T', b'U', b'V', b'W', b'X', // 2
43    b'Y', b'Z', b'a', b'b', b'c', b'd', b'e', b'f', // 3
44    b'g', b'h', b'i', b'j', b'k', b'l', b'm', b'n', // 4
45    b'o', b'p', b'q', b'r', b's', b't', b'u', b'v', // 5
46    b'w', b'x', b'y', b'z', b'0', b'1', b'2', b'3', // 6
47    b'4', b'5', b'6', b'7', b'8', b'9', b'+', b'/', // 7
48];
49
50#[cfg(test)]
51mod ut_util_base64 {
52    use crate::util::base64::encode;
53
54    /// UT test cases for `base64::encode`.
55    ///
56    /// # Brief
57    /// 1. Calls `encode` to parse the string and convert it into `base64`
58    ///    format.
59    /// 2. Checks if the results are correct.
60    #[test]
61    fn ut_util_base64_encode() {
62        assert_eq!(encode(b"this is an example"), b"dGhpcyBpcyBhbiBleGFtcGxl");
63        assert_eq!(encode(b"hello"), b"aGVsbG8=");
64        assert_eq!(encode(b""), b"");
65        assert_eq!(encode(b"a"), b"YQ==");
66        assert_eq!(encode(b"ab"), b"YWI=");
67        assert_eq!(encode(b"abc"), b"YWJj");
68    }
69}
70