use super::funejson::Value; use super::net_ipv4_parse_ipv4::ipv4_value; use super::net_ipv6_parse_ipv6::ipv6_groups; /// True for a well-formed IPv4 (prefix 0-32) or IPv6 (prefix 0-128) block; never panics. pub fn is_cidr(text: &str) -> bool { cidr_block(text).is_some() } // Exported for the other functions of this group; not part of its contract. /// The block as (version, bits, prefix): bits is [address] for version 4 and /// the eight groups for version 6. None when the text is not address/prefix /// with a strict decimal prefix. pub fn cidr_block(text: &str) -> Option<(i64, Vec, i64)> { let mut halves = text.split('/'); let address = halves.next()?; let digits = halves.next()?; if halves.next().is_some() { return None; } let bytes = digits.as_bytes(); if bytes.is_empty() || bytes.len() > 3 || !bytes.iter().all(|b| b.is_ascii_digit()) { return None; } if bytes.len() > 1 && bytes[0] == b'0' { return None; } let prefix = bytes.iter().fold(0i64, |acc, b| acc * 10 + (b - b'0') as i64); if let Some(v4) = ipv4_value(address) { return if prefix <= 32 { Some((4, vec![v4], prefix)) } else { None }; } if let Some(v6) = ipv6_groups(address) { return if prefix <= 128 { Some((6, v6, prefix)) } else { None }; } None } pub fn fune_vector(args: &[Value]) -> Value { Value::Bool(is_cidr(args[0].as_str())) }