Functional Weave
Code in Python

encoding.base64@1.0.0

impl/rust/base64_url_decode.rs

1,684 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
use super::encoding_base64_base64_decode::base64_decode;  ← base64Decode, another function of this group · built into the same file, even by a slim install

/// base64url text back to bytes. Padding is optional, since JWTs leave it
/// off and some producers keep it, but padding that is present must be right.
///
/// # Panics
/// Panics on a character outside the URL-safe alphabet, an impossible
/// length, wrong padding, or non-zero bits after the last byte.
pub fn base64_url_decode(text: &str) -> Vec<i64> {
    let mut body = String::with_capacity(text.len() + 2);
    let mut padding = 0usize;
    for &b in text.as_bytes() {
        if b == b'=' {
            padding += 1;
            continue;
        }
        let ok = b.is_ascii_alphanumeric() || b == b'-' || b == b'_';
        if !ok || padding > 0 {
            panic!("base64url text may only contain A-Z, a-z, 0-9, - and _, with optional = padding at the end");
        }
        body.push(match b {
            b'-' => '+',
            b'_' => '/',
            other => other as char,
        });
    }
    if body.len() % 4 == 1 {
        panic!(
            "base64url text cannot be {} characters long; no number of bytes encodes to that",
            body.len()
        );
    }
    let needed = (4 - body.len() % 4) % 4;
    if padding != 0 && padding != needed {
        panic!("base64url text has the wrong amount of = padding");
    }
    for _ in 0..needed {
        body.push('=');
    }
    base64_decode(&body)
}

pub fn fune_vector(args: &[Value]) -> Value {
    let text = match &args[0] {
        Value::Str(s) => s.as_str(),
        _ => panic!("base64url text must be a string"),
    };
    Value::Arr(base64_url_decode(text).into_iter().map(Value::Int).collect())
}