commit 98b2264491ec1ee111dbbdb01b5cfb9a476d61cf Author: Ed Guloien Date: Sun Apr 12 19:05:29 2026 -0400 init simple crate for doing base64 encoding/decoding diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..8dd0975 --- /dev/null +++ b/Cargo.lock @@ -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" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..62f14c5 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "base64" +version = "0.1.0" +edition = "2024" + +[dependencies] diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..393df2e --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,60 @@ + +const BASE64_ALPHABET: [u8; 64] = *b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +pub fn encode(bytes: Vec) -> String { + let mut output : Vec = 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> { + // 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==")); + } +}