Programming Language

Nocter

A self-contained systems language built around simplicity, encapsulation, and foolproof design.

/std/net/index.nct

index.nct

//! Numeric Internet addresses for synchronous network I/O.
//!
//! Target-independent address values, TCP byte streams, UDP datagrams, and monotonic operation
//! timeouts share one ownership and error model.

use /fmt.Format
use /hash.Hash
use /io.{Reader, Writer}
use /mem.TryAllocator
use /order.TotalOrder
use /string.String
use /time.Duration

see ./contracts.nct
see ./formatting.nct
see ./parsing.nct
see ./tests.nct
see ./tcp.nct
see ./errors.nct
see ./tcp_tests.nct
see ./udp.nct
see ./udp_tests.nct
see ./timeout_tests.nct
see ./values.nct

/// The Internet protocol address family represented by an `IpAddress`.
pub enum IpFamily {
    ipv4
    ipv6
}

/// One copyable 32-bit Internet Protocol version 4 address.
pub copy struct Ipv4Address

/// One copyable 128-bit Internet Protocol version 6 address.
pub copy struct Ipv6Address

/// One copyable numeric IPv4 or IPv6 address.
pub copy struct IpAddress

/// One copyable numeric IP address and logical transport port.
pub copy struct SocketAddress

/// One uniquely owned connected TCP byte stream.
pub struct TcpStream

/// One uniquely owned TCP listening socket.
pub struct TcpListener

/// One uniquely owned UDP datagram socket.
pub struct UdpSocket

/// The observable result of receiving exactly one UDP datagram.
pub copy struct DatagramRead

/// Connected TCP directions selected for local shutdown.
pub enum TcpShutdown {
    read
    write
    both
}

construct Ipv4Address {
    /// Creates an address from four octets in text order.
    pub noalloc func from_octets(first: u8, second: u8, third: u8, fourth: u8): Self

    /// Parses one complete dotted-decimal IPv4 spelling.
    pub noalloc func parse(text: &str): Self?

    /// Creates the unspecified address `0.0.0.0`.
    pub noalloc func unspecified(): Self

    /// Creates the loopback address `127.0.0.1`.
    pub noalloc func loopback(): Self
}

instance Ipv4Address {
    impl Format
    impl Hash
    impl TotalOrder

    /// Returns the four address octets in text order.
    pub noalloc method &self.octets(): [u8; 4]

    /// Reports whether this is the unspecified address.
    pub noalloc method &self.is_unspecified(): bool

    /// Reports whether this belongs to the `127.0.0.0/8` loopback range.
    pub noalloc method &self.is_loopback(): bool

    /// Returns the canonical dotted-decimal spelling.
    pub method self.to_string(): String

    /// Returns the canonical spelling using recoverable storage from `allocator`.
    pub method self.try_to_string(allocator: &+TryAllocator): String! from allocator

    /// Compares exact address octets.
    pub noalloc operator (&self == other: &Self): bool

    /// Orders exact address octets lexicographically.
    pub noalloc operator (&self < other: &Self): bool
}

construct Ipv6Address {
    /// Creates an address from eight 16-bit components in text order.
    pub noalloc func from_segments(
        first: u16,
        second: u16,
        third: u16,
        fourth: u16,
        fifth: u16,
        sixth: u16,
        seventh: u16,
        eighth: u16,
    ): Self

    /// Parses one complete numeric IPv6 spelling, including an optional embedded IPv4 tail.
    pub noalloc func parse(text: &str): Self?

    /// Creates the unspecified address `::`.
    pub noalloc func unspecified(): Self

    /// Creates the loopback address `::1`.
    pub noalloc func loopback(): Self
}

instance Ipv6Address {
    impl Format
    impl Hash
    impl TotalOrder

    /// Returns the eight 16-bit components in text order.
    pub noalloc method &self.segments(): [u16; 8]

    /// Reports whether this is the unspecified address.
    pub noalloc method &self.is_unspecified(): bool

    /// Reports whether this is the loopback address.
    pub noalloc method &self.is_loopback(): bool

    /// Returns the canonical RFC 5952 hexadecimal spelling.
    pub method self.to_string(): String

    /// Returns the canonical spelling using recoverable storage from `allocator`.
    pub method self.try_to_string(allocator: &+TryAllocator): String! from allocator

    /// Compares exact address octets.
    pub noalloc operator (&self == other: &Self): bool

    /// Orders exact address octets lexicographically.
    pub noalloc operator (&self < other: &Self): bool
}

construct IpAddress {
    /// Wraps one IPv4 address without changing its octets.
    pub noalloc func from_ipv4(address: Ipv4Address): Self

    /// Wraps one IPv6 address without changing its octets.
    pub noalloc func from_ipv6(address: Ipv6Address): Self

    /// Parses one complete numeric IPv4 or IPv6 spelling.
    pub noalloc func parse(text: &str): Self?
}

instance IpAddress {
    impl Format
    impl Hash
    impl TotalOrder

    /// Returns this address's explicit family.
    pub noalloc method &self.family(): IpFamily

    /// Returns the represented IPv4 address, or absence for IPv6.
    pub noalloc method &self.as_ipv4(): Ipv4Address?

    /// Returns the represented IPv6 address, or absence for IPv4.
    pub noalloc method &self.as_ipv6(): Ipv6Address?

    /// Returns the canonical numeric spelling.
    pub method self.to_string(): String

    /// Returns the canonical spelling using recoverable storage from `allocator`.
    pub method self.try_to_string(allocator: &+TryAllocator): String! from allocator

    /// Compares the family and exact address octets.
    pub noalloc operator (&self == other: &Self): bool

    /// Orders IPv4 before IPv6, then orders exact address octets lexicographically.
    pub noalloc operator (&self < other: &Self): bool
}

construct SocketAddress {
    /// Combines a numeric address with one logical transport port.
    pub noalloc func new(address: IpAddress, port: u16): Self

    /// Parses `IPv4:port` or `[IPv6]:port` from one complete input.
    pub noalloc func parse(text: &str): Self?
}

instance SocketAddress {
    impl Format
    impl Hash
    impl TotalOrder

    /// Returns the numeric IP address.
    pub noalloc method &self.ip(): IpAddress

    /// Returns the logical transport port.
    pub noalloc method &self.port(): u16

    /// Returns the canonical address and decimal port spelling.
    pub method self.to_string(): String

    /// Returns the canonical spelling using recoverable storage from `allocator`.
    pub method self.try_to_string(allocator: &+TryAllocator): String! from allocator

    /// Compares the logical IP address and port.
    pub noalloc operator (&self == other: &Self): bool

    /// Orders by logical IP address, then by port.
    pub noalloc operator (&self < other: &Self): bool
}

construct TcpStream {
    /// Connects synchronously to one numeric socket address.
    pub noalloc func connect(address: SocketAddress): Self!

    /// Connects synchronously, returning `std.net.timed_out` when `timeout` expires.
    pub noalloc func connect_with_timeout(address: SocketAddress, timeout: Duration): Self!
}

instance TcpStream {
    impl Reader
    impl Writer

    /// Returns the effective local socket address.
    pub noalloc method &self.local_address(): SocketAddress!

    /// Returns the connected peer socket address.
    pub noalloc method &self.peer_address(): SocketAddress!

    /// Replaces the read timeout; absence permits an unlimited wait.
    pub noalloc method &+self.set_read_timeout(timeout: Duration?): void

    /// Returns the configured read timeout.
    pub noalloc method &self.read_timeout(): Duration?

    /// Replaces the write timeout; absence permits an unlimited wait.
    pub noalloc method &+self.set_write_timeout(timeout: Duration?): void

    /// Returns the configured write timeout.
    pub noalloc method &self.write_timeout(): Duration?

    /// Shuts down selected local stream directions without closing the socket.
    pub noalloc method &+self.shutdown(direction: TcpShutdown): void!

    /// Makes the stream terminal and releases its descriptor at most once.
    pub noalloc method &+self.close(): void
}

construct TcpListener {
    /// Binds one numeric address and starts listening with the platform's standard backlog.
    pub noalloc func bind(address: SocketAddress): Self!
}

instance TcpListener {
    /// Returns the effective local address, including a kernel-selected port.
    pub noalloc method &self.local_address(): SocketAddress!

    /// Accepts one connected stream and returns its peer address.
    pub noalloc method &+self.accept(): (TcpStream, SocketAddress)!

    /// Replaces the accept timeout; absence permits an unlimited wait.
    pub noalloc method &+self.set_accept_timeout(timeout: Duration?): void

    /// Returns the configured accept timeout.
    pub noalloc method &self.accept_timeout(): Duration?

    /// Makes the listener terminal and releases its descriptor at most once.
    pub noalloc method &+self.close(): void
}

construct UdpSocket {
    /// Binds one numeric local address for datagram communication.
    pub noalloc func bind(address: SocketAddress): Self!
}

instance UdpSocket {
    /// Connects this socket to one peer for subsequent `send` operations.
    pub noalloc method &+self.connect(peer: SocketAddress): void!

    /// Sends one complete datagram to the connected peer.
    pub noalloc method &+self.send(bytes: &[u8]): void!

    /// Sends one complete datagram to an explicit peer.
    pub noalloc method &+self.send_to(bytes: &[u8], target: SocketAddress): void!

    /// Receives one datagram and reports source, copied length, and truncation.
    pub noalloc method &+self.receive(buffer: &+[u8]): DatagramRead!

    /// Returns the effective local address, including a kernel-selected port.
    pub noalloc method &self.local_address(): SocketAddress!

    /// Returns the connected peer address or an error when no peer is connected.
    pub noalloc method &self.peer_address(): SocketAddress!

    /// Replaces the receive timeout; absence permits an unlimited wait.
    pub noalloc method &+self.set_read_timeout(timeout: Duration?): void

    /// Returns the configured receive timeout.
    pub noalloc method &self.read_timeout(): Duration?

    /// Replaces the connect and send timeout; absence permits an unlimited wait.
    pub noalloc method &+self.set_write_timeout(timeout: Duration?): void

    /// Returns the configured connect and send timeout.
    pub noalloc method &self.write_timeout(): Duration?

    /// Makes the socket terminal and releases its descriptor at most once.
    pub noalloc method &+self.close(): void
}

instance DatagramRead {
    /// Returns the sender of the consumed datagram.
    pub noalloc method &self.source(): SocketAddress

    /// Returns how many bytes were copied into the supplied buffer.
    pub noalloc method &self.copied_len(): usize

    /// Reports whether the consumed datagram exceeded the supplied buffer.
    pub noalloc method &self.was_truncated(): bool
}