Functional Weave
Code in TypeScript

net.ipv6@1.0.0

impl/rust/format_ipv6.rs

1,820 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::net_ipv4_format_ipv4::format_ipv4;

/// RFC 5952 canonical text for eight 16-bit groups.
///
/// Lower-case hex, no leading zeros, the longest run of two or more zero
/// groups written "::" (the first on a tie, never a single group). An
/// IPv4-mapped address (::ffff:0:0/96) keeps its dotted-quad tail.
///
/// # Panics
/// Panics unless there are exactly eight groups, each 0 to 65535.
pub fn format_ipv6(groups: &[i64]) -> String {
    if groups.len() != 8 || groups.iter().any(|g| !(0..=65535).contains(g)) {
        panic!("IPv6 groups must be eight integers from 0 to 65535");
    }
    if groups[..6] == [0, 0, 0, 0, 0, 0xffff] {
        return format!("::ffff:{}", format_ipv4(groups[6] * 65536 + groups[7]));
    }
    let (mut best_start, mut best_length) = (0usize, 0usize);
    let mut i = 0;
    while i < 8 {
        if groups[i] != 0 {
            i += 1;
            continue;
        }
        let mut j = i;
        while j < 8 && groups[j] == 0 {
            j += 1;
        }
        // Strictly longer, so the first of two equal runs wins.
        if j - i > best_length {
            best_start = i;
            best_length = j - i;
        }
        i = j;
    }
    let hex: Vec<String> = groups.iter().map(|g| format!("{:x}", g)).collect();
    if best_length < 2 {
        return hex.join(":");
    }
    format!(
        "{}::{}",
        hex[..best_start].join(":"),
        hex[best_start + best_length..].join(":")
    )
}

pub fn fune_vector(args: &[Value]) -> Value {
    let groups: Vec<i64> = args[0]
        .as_arr()
        .iter()
        .map(|g| match g {
            Value::Int(i) => *i,
            _ => panic!("IPv6 groups must be eight integers from 0 to 65535"),
        })
        .collect();
    Value::str(&format_ipv6(&groups))
}