Functional Weave
Code in Rust

encoding.hex@1.0.0

impl/rust/hex_encode.rs

1,504 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 DIGITS: &[u8; 16] = b"0123456789abcdef";

/// Bytes as lowercase hexadecimal, two digits per byte.
///
/// Bytes are a list of integers 0-255 across the registry (there is no bytes
/// type), so a value outside that range is refused rather than masked to a
/// byte: 256 quietly becoming 0 would change key material without a trace.
///
/// # Panics
/// Panics if any value is outside 0-255.
pub fn hex_encode(bytes: &[i64]) -> String {
    let mut out = String::with_capacity(bytes.len() * 2);
    for &b in bytes {
        if !(0..=255).contains(&b) {
            panic!("bytes must be a list of integers from 0 to 255");
        }
        out.push(DIGITS[(b >> 4) as usize] as char);
        out.push(DIGITS[(b & 15) as usize] as char);
    }
    out
}

/// A JSON list of byte values, refusing what the other languages refuse (a
/// fraction, a string, a boolean) with the same words instead of letting
/// `as_i64` turn it into a number.
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(&hex_encode(&bytes_from_value(&args[0], "bytes")))
}