Functional Weave
Code in TypeScript

net.cidr@1.0.0

impl/rust/cidr_contains.rs

1,472 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_cidr_is_cidr::cidr_block;  ← isCidr, another function of this group · built into the same file, even by a slim install
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()))
}