wasm-rquickjs 0.3.4

Tool for wrapping JavaScript modules as WebAssembly components using the QuickJS engine
Documentation
use rquickjs::{Ctx, Exception};
use wasip2::sockets::network::{
    ErrorCode, IpAddress, IpSocketAddress, Ipv4SocketAddress, Ipv6SocketAddress,
};

pub fn parse_ip_address(addr: &str) -> Option<IpAddress> {
    use std::net::IpAddr;
    match addr.parse::<IpAddr>() {
        Ok(IpAddr::V4(v4)) => {
            let octets = v4.octets();
            Some(IpAddress::Ipv4((
                octets[0], octets[1], octets[2], octets[3],
            )))
        }
        Ok(IpAddr::V6(v6)) => {
            let segs = v6.segments();
            Some(IpAddress::Ipv6((
                segs[0], segs[1], segs[2], segs[3], segs[4], segs[5], segs[6], segs[7],
            )))
        }
        Err(_) => None,
    }
}

pub fn ip_socket_address(ip: IpAddress, port: u16) -> IpSocketAddress {
    match ip {
        IpAddress::Ipv4(addr) => IpSocketAddress::Ipv4(Ipv4SocketAddress {
            port,
            address: addr,
        }),
        IpAddress::Ipv6(addr) => IpSocketAddress::Ipv6(Ipv6SocketAddress {
            port,
            flow_info: 0,
            address: addr,
            scope_id: 0,
        }),
    }
}

pub fn ip_address_to_string(addr: &IpSocketAddress) -> String {
    match addr {
        IpSocketAddress::Ipv4(a) => {
            let (a1, b, c, d) = a.address;
            format!("{a1}.{b}.{c}.{d}")
        }
        IpSocketAddress::Ipv6(a) => {
            let (a1, b, c, d, e, f, g, h) = a.address;
            format!("{a1:x}:{b:x}:{c:x}:{d:x}:{e:x}:{f:x}:{g:x}:{h:x}")
        }
    }
}

pub fn ip_socket_address_port(addr: &IpSocketAddress) -> u16 {
    match addr {
        IpSocketAddress::Ipv4(a) => a.port,
        IpSocketAddress::Ipv6(a) => a.port,
    }
}

pub fn ip_socket_address_family(addr: &IpSocketAddress) -> &str {
    match addr {
        IpSocketAddress::Ipv4(_) => "IPv4",
        IpSocketAddress::Ipv6(_) => "IPv6",
    }
}

pub fn error_code_to_errno(error: ErrorCode) -> &'static str {
    match error {
        ErrorCode::AddressInUse => "EADDRINUSE",
        ErrorCode::AddressNotBindable => "EADDRNOTAVAIL",
        ErrorCode::InvalidArgument => "EINVAL",
        ErrorCode::InvalidState => "EINVAL",
        ErrorCode::AccessDenied => "EACCES",
        ErrorCode::RemoteUnreachable => "EHOSTUNREACH",
        ErrorCode::ConnectionRefused => "ECONNREFUSED",
        ErrorCode::DatagramTooLarge => "EMSGSIZE",
        ErrorCode::NewSocketLimit => "EMFILE",
        ErrorCode::ConnectionReset => "ECONNRESET",
        ErrorCode::ConnectionAborted => "ECONNABORTED",
        ErrorCode::Timeout => "ETIMEDOUT",
        ErrorCode::NotSupported => "ENOSYS",
        ErrorCode::ConcurrencyConflict => "EALREADY",
        ErrorCode::NotInProgress => "EINVAL",
        _ => "EIO",
    }
}

pub fn throw_socket_error(
    ctx: &Ctx<'_>,
    code: &str,
    syscall: &str,
    message: &str,
) -> rquickjs::Error {
    let escaped = message.replace('\\', "\\\\").replace('"', "\\\"");
    Exception::throw_message(
        ctx,
        &format!("{{\"code\":\"{code}\",\"syscall\":\"{syscall}\",\"message\":\"{escaped}\"}}"),
    )
}