shuyi_platform/link/
base64.rs1use crate::alloc_prelude::*;
5use alloc::format;
6
7const ALPHABET: &[u8; 64] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
9
10pub fn encode(bytes: &[u8]) -> String {
12 let mut out = String::with_capacity(bytes.len().div_ceil(3) * 4);
13 for chunk in bytes.chunks(3) {
14 let n = u32::from_be_bytes([
15 0,
16 chunk[0],
17 chunk.get(1).copied().unwrap_or(0),
18 chunk.get(2).copied().unwrap_or(0),
19 ]);
20 for i in 0..4 {
21 if i <= chunk.len() {
22 out.push(char::from(ALPHABET[((n >> (18 - 6 * i)) & 63) as usize]));
23 } else {
24 out.push('=');
25 }
26 }
27 }
28 out
29}
30
31fn value(c: u8) -> Option<u32> {
33 let v = match c {
34 b'A'..=b'Z' => c - b'A',
35 b'a'..=b'z' => c - b'a' + 26,
36 b'0'..=b'9' => c - b'0' + 52,
37 b'+' => 62,
38 b'/' => 63,
39 _ => return None,
40 };
41 Some(u32::from(v))
42}
43
44pub fn decode(text: &str) -> Result<Vec<u8>, String> {
47 let bytes = text.as_bytes();
48 if !bytes.len().is_multiple_of(4) {
49 return Err(format!(
50 "base64: {} characters, not a multiple of 4",
51 bytes.len()
52 ));
53 }
54 let mut out = Vec::with_capacity(bytes.len() / 4 * 3);
55 let quads = bytes.len() / 4;
56 for (i, quad) in bytes.chunks(4).enumerate() {
57 let pad = quad.iter().rev().take_while(|&&c| c == b'=').count();
58 if pad > 2 || (pad > 0 && i + 1 != quads) {
59 return Err("base64: padding before the end".to_owned());
60 }
61 let mut n = 0u32;
62 for &c in &quad[..4 - pad] {
63 let v = value(c)
64 .ok_or_else(|| format!("base64: {:?} is no base64 character", char::from(c)))?;
65 n = n * 64 + v;
66 }
67 n <<= 6 * pad;
68 let [_, a, b, c] = n.to_be_bytes();
69 out.extend_from_slice(&[a, b, c][..3 - pad]);
70 }
71 Ok(out)
72}