Functional Weave
Code in Rust

charts.color@1.0.1

impl/rust/parse_hex.rs

1,298 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

fn nibble(ch: u8, hex: &str) -> i64 {
    match ch {
        b'0'..=b'9' => i64::from(ch - b'0'),
        b'a'..=b'f' => i64::from(ch - b'a') + 10,
        b'A'..=b'F' => i64::from(ch - b'A') + 10,
        _ => panic!("\"{}\" is not a hex colour (#rgb or #rrggbb)", hex),
    }
}

/// "#rrggbb" or the short "#rgb" (digits doubled, as CSS does), either case.
///
/// # Panics
/// Panics on anything else.
pub fn parse_hex(hex: &str) -> Rgb {
    let bytes = hex.as_bytes();
    if bytes.first() != Some(&b'#') || (bytes.len() != 4 && bytes.len() != 7) {
        panic!("\"{}\" is not a hex colour (#rgb or #rrggbb)", hex);
    }
    if bytes.len() == 4 {
        return Rgb {
            r: nibble(bytes[1], hex) * 17,
            g: nibble(bytes[2], hex) * 17,
            b: nibble(bytes[3], hex) * 17,
        };
    }
    Rgb {
        r: nibble(bytes[1], hex) * 16 + nibble(bytes[2], hex),
        g: nibble(bytes[3], hex) * 16 + nibble(bytes[4], hex),
        b: nibble(bytes[5], hex) * 16 + nibble(bytes[6], hex),
    }
}

pub fn rgb_to_value(rgb: &Rgb) -> Value {
    Value::obj(vec![("r", Value::Int(rgb.r)), ("g", Value::Int(rgb.g)), ("b", Value::Int(rgb.b))])
}

pub fn fune_vector(args: &[Value]) -> Value {
    rgb_to_value(&parse_hex(args[0].as_str()))
}