use super::funejson::Value; const ALPHABET: &[u8; 64] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; /// Bytes as standard base64 (RFC 4648 section 4), padded with "=". /// /// # Panics /// Panics if any value is outside 0-255. pub fn base64_encode(bytes: &[i64]) -> String { if bytes.iter().any(|b| !(0..=255).contains(b)) { panic!("bytes must be a list of integers from 0 to 255"); } let mut out = String::with_capacity((bytes.len() + 2) / 3 * 4); let push = |out: &mut String, n: i64, count: usize| { for k in 0..4 { if k < count { out.push(ALPHABET[((n >> (18 - 6 * k)) & 63) as usize] as char); } else { out.push('='); } } }; let mut chunks = bytes.chunks_exact(3); for c in &mut chunks { push(&mut out, (c[0] << 16) | (c[1] << 8) | c[2], 4); } match chunks.remainder() { [a] => push(&mut out, a << 16, 2), [a, b] => push(&mut out, (a << 16) | (b << 8), 3), _ => {} } out } fn bytes_from_value(value: &Value, name: &str) -> Vec { match value { Value::Arr(items) => items .iter() .map(|item| match item { Value::Int(i) => *i, _ => panic!("{} must be a list of integers from 0 to 255", name), }) .collect(), _ => panic!("{} must be a list of integers from 0 to 255", name), } } pub fn fune_vector(args: &[Value]) -> Value { Value::str(&base64_encode(&bytes_from_value(&args[0], "bytes"))) }