use super::funejson::Value; 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 = 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 = 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)) }