Functional Weave
Code in TypeScript

net.cidr@1.0.0

impl/rust/cidr_info.rs

2,236 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_format_ipv4::format_ipv4;

/// Everything a subnet calculator shows for one IPv4 block.
///
/// Host bits in the input are dropped (192.168.1.77/24 describes
/// 192.168.1.0/24). A /31 is a point-to-point link with two usable addresses
/// and no broadcast (RFC 3021); a /32 is one host.
///
/// # Panics
/// Panics on a malformed block or an IPv6 block.
pub fn cidr_info(cidr: &str) -> CidrInfo {
    let (version, bits, prefix) = match cidr_block(cidr) {
        Some(block) => block,
        None => panic!("\"{}\" is not a CIDR block", cidr),
    };
    if version != 4 {
        panic!("cidrInfo handles IPv4 blocks only, received \"{}\"", cidr);
    }
    let size: i64 = 1 << (32 - prefix);
    let network = bits[0] - bits[0] % size;
    let last = network + size - 1;
    let point_to_point = prefix >= 31;
    CidrInfo {
        cidr: format!("{}/{}", format_ipv4(network), prefix),
        network: format_ipv4(network),
        prefix,
        netmask: format_ipv4(4294967296 - size),
        wildcard: format_ipv4(size - 1),
        broadcast: if point_to_point { None } else { Some(format_ipv4(last)) },
        first_host: format_ipv4(if point_to_point { network } else { network + 1 }),
        last_host: format_ipv4(if point_to_point { last } else { last - 1 }),
        host_count: if point_to_point { size } else { size - 2 },
        address_count: size,
    }
}

pub fn cidr_info_to_value(info: &CidrInfo) -> Value {
    Value::obj(vec![
        ("cidr", Value::str(&info.cidr)),
        ("network", Value::str(&info.network)),
        ("prefix", Value::Int(info.prefix)),
        ("netmask", Value::str(&info.netmask)),
        ("wildcard", Value::str(&info.wildcard)),
        ("broadcast", match &info.broadcast {
            Some(b) => Value::str(b),
            None => Value::Null,
        }),
        ("firstHost", Value::str(&info.first_host)),
        ("lastHost", Value::str(&info.last_host)),
        ("hostCount", Value::Int(info.host_count)),
        ("addressCount", Value::Int(info.address_count)),
    ])
}

pub fn fune_vector(args: &[Value]) -> Value {
    cidr_info_to_value(&cidr_info(args[0].as_str()))
}