typub_storage/
encoding.rs1use std::path::Path;
4
5pub fn to_data_uri(data: &[u8], path: &Path) -> String {
7 let mime = crate::mime_type_from_path(path);
8 let b64 = base64_encode(data);
9 format!("data:{};base64,{}", mime, b64)
10}
11
12pub fn base64_encode(data: &[u8]) -> String {
14 const ALPHABET: &[u8; 64] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
15
16 let mut result = String::new();
17 for chunk in data.chunks(3) {
18 let mut val = 0u32;
19 for (i, &byte) in chunk.iter().enumerate() {
20 val |= (byte as u32) << (16 - 8 * i);
21 }
22
23 let chars = match chunk.len() {
24 1 => 2,
25 2 => 3,
26 _ => 4,
27 };
28
29 for i in 0..chars {
30 let idx = ((val >> (18 - 6 * i)) & 0x3F) as usize;
31 result.push(ALPHABET[idx] as char);
32 }
33
34 for _ in chars..4 {
35 result.push('=');
36 }
37 }
38
39 result
40}
41
42#[cfg(test)]
43mod tests {
44 #![allow(clippy::expect_used)]
45 use super::*;
46
47 #[test]
48 fn test_base64_encode_empty() {
49 assert_eq!(base64_encode(&[]), "");
50 }
51
52 #[test]
53 fn test_base64_encode_hello() {
54 assert_eq!(base64_encode(b"Hello"), "SGVsbG8=");
56 }
57
58 #[test]
59 fn test_base64_encode_padding() {
60 assert_eq!(base64_encode(b"a"), "YQ==");
62 assert_eq!(base64_encode(b"ab"), "YWI=");
64 assert_eq!(base64_encode(b"abc"), "YWJj");
66 }
67
68 #[test]
69 fn test_to_data_uri() {
70 let data = b"test";
71 let path = Path::new("image.png");
72 let uri = to_data_uri(data, path);
73 assert!(uri.starts_with("data:image/png;base64,"));
74 }
75}