W# 0.1.1

Networking and messages

std/net, std/http and std/broker.

std/net

const net = @import("std/net");

TCP, UDP and readiness, over the syscalls the runtime declares by hand. IPv4 or IPv6, with the family the resolver’s choice.

TCP. Socket and Listener, with connect listen accept read write write_all read_exactly read_all set_nonblocking close.

UDP. Datagrams Peer and Datagram, with udp send_to receive reply.

Readiness. Poller and Event, with poller watch wait.

const net = @import("std/net");

fn main() i64 {
    const l = net.listen("127.0.0.1", 8080, 16) catch return 1;
    const c = net.accept(l) catch return 2;
    net.write_all(c, "hello\n") catch return 3;
    net.close(c);
    return 0;
}

A blocking read is safe rather than merely tolerated: a builtin that blocks does so inside a safe region, so the collector can walk this worker’s stack and run its pauses while the thread waits on the network. net.poller is for serving many connections from one worker, not for keeping the collector alive.

std/http

const http = @import("std/http");

An HTTP/1.1 client and server, and the 27 status types that dispatch is demonstrated on.

get(url) !Response, post(url, body) !Response, request(...) !Responseclient
read_request(conn) !Request, respond(conn, code, type, body) !voidserver
header(r, name) ?str
status_of(code) Statusthe code as its type
Status, Status1xx to Status5xx, and 22 exact codesthe lattice

https:// works, over std/tls, with the chain verified against the root store the machine already has. Every part of that handshake is a .ws file compiled into your program.

const http = @import("std/http");
const text = @import("std/str");

fn main() i64 {
    const answer = http.get("https://wsharp.io/") catch return 1;
    print_int(answer.code);
    print_int(text.len(answer.body));
    return 0;
}

A server:

const net  = @import("std/net");
const http = @import("std/http");

fn main() i64 {
    const l = net.listen("127.0.0.1", 8080, 16) catch return 1;
    const c = http.connection(net.accept(l) catch return 2);
    const request = http.read_request(c) catch return 3;
    http.respond(c, 200, "text/plain", request.path) catch return 4;
    return 0;
}

The status types are materialised on first mention, so a program that never names one pays nothing for the other 26.

std/broker

const broker = @import("std/broker");

Kafka’s shape: named topics, partitioned logs, consumer groups with their own offsets, and replay. It is the counterpart to a worker call, for when the caller does not need the answer or when more than one worker wants the same message.

topic(name, partitions) Topic[M]
publish(t, key, message) voidthe key chooses the partition
subscribe(t, group) Consumer[M]
next(c) ?Mwhich is why the loop is a while with a capture
commit(c) void, seek(c, offset) void
len(t) i64
var audit: broker.Topic[Event] = broker.topic("audit", 2);
broker.publish(audit, "orders", Finished{ .at = 1, .count = 5 });

var reader: broker.Consumer[Event] = broker.subscribe(audit, "report");
while (broker.next(reader)) |e| { report(e); }
broker.commit(reader);

A subscriber set is an overload set. report being three functions over Event and its subtypes means choosing between them is the dispatcher, one subtract and one unsigned compare on the type id the message carried with it. Nothing in the broker knows those functions exist. See workers.

Last changed 8 September 2026. Improve this page

On this page