use super::funejson::Value; use super::net_cidr_is_cidr::cidr_block; use super::net_ipv4_parse_ipv4::ipv4_value; use super::net_ipv6_parse_ipv6::ipv6_groups; /// Whether an address lies inside a block, IPv4 or IPv6. /// /// An address of the other family is never inside (an IPv4-mapped IPv6 /// address is not treated as its IPv4 address). /// /// # Panics /// Panics on a malformed block or address. pub fn cidr_contains(cidr: &str, address: &str) -> bool { let (version, bits, prefix) = match cidr_block(cidr) { Some(block) => block, None => panic!("\"{}\" is not a CIDR block", cidr), }; let v4 = ipv4_value(address); let v6 = if v4.is_none() { ipv6_groups(address) } else { None }; if v4.is_none() && v6.is_none() { panic!("\"{}\" is not an IP address", address); } if version == 4 { return match v4 { None => false, Some(a) => { let size: i64 = 1 << (32 - prefix); a / size == bits[0] / size } }; } let groups = match v6 { None => return false, Some(g) => g, }; for i in 0..8 { let taken = (prefix - 16 * i as i64).clamp(0, 16); let size: i64 = 1 << (16 - taken); if groups[i] / size != bits[i] / size { return false; } } true } pub fn fune_vector(args: &[Value]) -> Value { Value::Bool(cidr_contains(args[0].as_str(), args[1].as_str())) }