Functional Weave
Code in TypeScript

net.port@1.0.0

impl/rust/port_service.rs

2,078 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_port_data::SERVICES;  ← this capability’s own data, compiled from data/services.json into the same file by fune build
use super::net_port_is_port::is_port;  ← isPort, another function of this group · built into the same file, even by a slim install

/// The RFC 6335 range a port is in, and the IANA service registered on it for
/// a protocol. A port with nothing in this registry's table has a null service:
/// unassigned, or assigned but not common enough to ship here.
///
/// # Panics
/// Panics on a port outside 1..=65535 or a protocol other than tcp or udp.
pub fn port_service(port: i64, protocol: &str) -> PortService {
    if !is_port(port) {
        panic!("port must be 1 to 65535, received {}", port);
    }
    if protocol != "tcp" && protocol != "udp" {
        panic!("protocol must be tcp or udp, received \"{}\"", protocol);
    }
    // RFC 6335 section 6: system 0-1023, user 1024-49151, dynamic 49152-65535.
    let range = if port <= 1023 {
        "system"
    } else if port <= 49151 {
        "user"
    } else {
        "dynamic"
    };
    let row = SERVICES.iter().find(|s| s.port == port && s.protocol == protocol);
    PortService {
        port,
        protocol: protocol.to_string(),
        range: range.to_string(),
        service: row.map(|r| r.service.to_string()),
        description: row.map(|r| r.description.to_string()),
    }
}

/// Object keys are camelCase to match the shared vectors.
pub fn port_service_to_value(result: &PortService) -> Value {
    let text = |field: &Option<String>| match field {
        Some(s) => Value::str(s),
        None => Value::Null,
    };
    Value::obj(vec![
        ("port", Value::Int(result.port)),
        ("protocol", Value::str(&result.protocol)),
        ("range", Value::str(&result.range)),
        ("service", text(&result.service)),
        ("description", text(&result.description)),
    ])
}

pub fn fune_vector(args: &[Value]) -> Value {
    // Refuse what an i64 cannot hold, with the wording TypeScript and Python use.
    let port = match &args[0] {
        Value::Int(i) => *i,
        other => panic!("port must be an integer, received {}", other),
    };
    port_service_to_value(&port_service(port, args[1].as_str()))
}