Functional Weave
Code in Python

encoding.base64@1.0.0

impl/rust/base64_encode.rs

1,603 bytes · the Rust implementation · view raw

Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.

use super::funejson::Value;  ← the fune runtime: the JSON value the test vectors use; fune build keeps it only where a signature takes one

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<i64> {
    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")))
}