init simple crate for doing base64 encoding/decoding

This commit is contained in:
2026-04-12 19:05:29 -04:00
commit 98b2264491
4 changed files with 74 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
/target
Generated
+7
View File
@@ -0,0 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "base64"
version = "0.1.0"
+6
View File
@@ -0,0 +1,6 @@
[package]
name = "base64"
version = "0.1.0"
edition = "2024"
[dependencies]
+60
View File
@@ -0,0 +1,60 @@
const BASE64_ALPHABET: [u8; 64] = *b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
pub fn encode(bytes: Vec<u8>) -> String {
let mut output : Vec<char> = Vec::new();
for chunk in bytes.chunks(3) {
let b0 = chunk.get(0).copied().unwrap_or(0) as u32;
let b1 = chunk.get(1).copied().unwrap_or(0) as u32;
let b2 = chunk.get(2).copied().unwrap_or(0) as u32;
// 24-bit number
let triple = (b0 << 16) | (b1 << 8) | b2;
// in 6-bit indices
let i0 = ((triple >> 18) & 0x3F) as usize;
let i1 = ((triple >> 12) & 0x3F) as usize;
let i2 = ((triple >> 6) & 0x3F) as usize;
let i3 = (triple & 0x3F) as usize;
// at least 1 chunk of 8-bit input
// so at least 2 chunks of 6-bit window is valid
output.push(BASE64_ALPHABET[i0] as char);
output.push(BASE64_ALPHABET[i1] as char);
match chunk.len() {
1 => {
output.push('=');
output.push('=');
},
2 => {
output.push(BASE64_ALPHABET[i2] as char);
output.push('=');
},
3 => {
output.push(BASE64_ALPHABET[i2] as char);
output.push(BASE64_ALPHABET[i3] as char);
},
_ => unreachable!()
}
}
output.into_iter().collect()
}
pub fn decode(_b64_str: &String) -> Option<Vec<u8>> {
// todo
Some(vec!()) // dummy
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_encode() {
let input = "f";
let bytes = input.as_bytes().to_vec();
let base64 = encode(bytes);
assert_eq!(base64, String::from("Zg=="));
}
}