#!/usr/bin/env dub
/+ dub.sdl:
name "eh_tcp_echo"
dependency "sparkles:event-horizon" path="../../../../.."
buildType "checked" {
buildOptions "optimize" "inline" "debugInfo"
}
platforms "linux"
+/
import (package) corecore.(module) core.lifetimelifetime : (alias template) eh_tcp_echo.move = core.lifetime.move(T)(ref T source, ref T target)Moves source into target, via a destructive copy when necessary.
If T is a struct with a destructor or postblit defined, source is reset
to its .init value after it is moved into target, otherwise it is
left unchanged.
Preconditions
If source has internal pointers that point to itself and doesn't define
opPostMove, it cannot be moved, and will trigger an assertion failure.
move;
import (package) stdstd.(module) std.stdioCategory Symbols File handles _popen File isFileHandle openNetwork stderr stdin stdout Reading chunks lines readf readfln readln Writing toFile write writef writefln writeln Misc KeepTerminator LockType StdioException
Standard I/O functions that extend core.stdc.stdio. core.stdc.stdio
is publically imported when importing std.stdio.
There are three layers of I/O:
The lowest layer is the operating system layer. The two main schemes are Windows and Posix.
C's stdio.h which unifies the two operating system schemes.
std.stdio, this module, unifies the various stdio.h implementations into
a high level package for D programs.
Source
std/stdio.d
stdio : (alias template) eh_tcp_echo.writeln = std.stdio.writeln(T...)(T args)Equivalent to write(args, '\n'). Calling writeln without
arguments is valid and just prints a newline to the standard
output.
Example
Reads stdin and writes it to stdout with an argument
counter.
import std.stdio;
void main()
{
string line;
for (size_t count = 0; (line = readln) !is null; count++)
{
writeln("Input ", count, ": ", line);
}
}
writeln;
import (package) sparklessparkles.(package) sparkles.basebase.(module) sparkles.base.bufferA @nogc container with Small Buffer Optimization (SBO).
Provides an append-only buffer that stores small amounts of data inline
(avoiding heap allocation) and automatically switches to heap storage
when capacity is exceeded.
Primary use case: appending elements in a temporary scope where GC
allocation is not desired.
buffer : (alias template) eh_tcp_echo.UniqueBuffer = sparkles.base.buffer.UniqueBuffer(T, ulong N = max(size_t(1), (T[]).sizeof / T.sizeof))Small-buffer optimization with a sole owner: inline while the elements fit, heap
when they do not, and copying is disabled.
Disabling copies is what removes the reference count from the grow path — there
is no second owner to consult. Hand a finished one to the shared world with
toShared, which consumes it and transfers any heap block without reallocating.
UniqueBuffer;
import (package) sparklessparkles.(module) sparkles.event_horizonsparkles:event-horizon — the completion-first event loop with a native
algebraic-effect layer. This package module re-exports the public surface
(SPEC §16); import sparkles.event_horizon`` for the whole API, or a specific
module for a narrower dependency.
event_horizon;
void void D main()main()
{
(struct) sparkles.event_horizon.group.LoopGroupA running loop group. Non-copyable; owns its worker scheduler(s).
LoopGroup (local variable) sparkles.event_horizon.group.LoopGroup groupgroup;
if ((struct) sparkles.event_horizon.group.LoopGroupA running loop group. Non-copyable; owns its worker scheduler(s).
LoopGroup.expected.Expected!(void, IoError, NoGcHook) sparkles.event_horizon.group.LoopGroup.start(out sparkles.event_horizon.group.LoopGroup group, in sparkles.event_horizon.group.LoopGroupConfig cfg = LoopGroupConfig(Topology.single, 0u, 256u, Flag.yes, Flag.yes, 256u, Flag.no))Probes the kernel and starts the group. io_uring probe failure is a
hard error (SPEC §3.4 — no epoll fallback).
start((local variable) sparkles.event_horizon.group.LoopGroup groupgroup).bool expected.Expected!(void, sparkles.base.io.errors.IoError, sparkles.base.text.errors.NoGcHook).hasError!()() const pure nothrow @nogc @property @safeChecks if Expected has error
hasError)
assert(false, "no completion backend");
scope (exit) (local variable) sparkles.event_horizon.group.LoopGroup groupgroup.void sparkles.event_horizon.group.LoopGroup.shutdown(core.time.Duration grace = dur(5L)) nothrow @safeTears down the group's workers.
shutdown();
auto (local variable) _error_ runrun = (local variable) sparkles.event_horizon.group.LoopGroup groupgroup.group.runrun((ref (alias) sparkles.event_horizon.group.RootScope = sparkles.event_horizon.scope_.Scope!(Sched, IoError)The blessed live scope instantiation handed to the root fiber (SPEC §7.2,
§11): a Scope over the ring-backed Sched executor with the IoError
channel.
RootScope (parameter) sparkles.event_horizon.scope_.Scope!(Sched, IoError) scsc, ref (alias) sparkles.event_horizon.live.Env = sparkles.event_horizon.capability.Ctx!(RingClock, RingVfs, RingNet, RingProc)The default live capability row handed to the root fiber (SPEC §11).
fs is on every backend: RingVfs needs no ring file operations
(SPEC §10.5).
Env (parameter) sparkles.event_horizon.capability.Ctx!(RingClock, RingVfs, RingNet, RingProc) envenv) {
auto (local variable) expected.Expected!(Listener, IoError, NoGcHook) listeninglistening = (parameter) sparkles.event_horizon.capability.Ctx!(RingClock, RingVfs, RingNet, RingProc) envenv.net.expected.Expected!(Listener, IoError, NoGcHook) sparkles.event_horizon.live.RingNet.listen(sparkles.event_horizon.net.SockAddr at, int backlog = 128) nothrow @trustedCreates a TCP socket, binds it to at, and listens.
listen(sparkles.event_horizon.net.SockAddr sparkles.event_horizon.net.ipv4(string dottedQuad, ushort port) pure nothrow @nogc @safeBuilds an IPv4 SockAddr (AF_INET, network byte order).
ipv4("127.0.0.1", 0));
assert((local variable) expected.Expected!(Listener, IoError, NoGcHook) listeninglistening.bool expected.Expected!(sparkles.event_horizon.io.Listener, sparkles.base.io.errors.IoError, sparkles.base.text.errors.NoGcHook).hasValue!()() const pure nothrow @nogc @property @safeChecks if Expected has value
hasValue);
auto (local variable) sparkles.event_horizon.io.Listener listenerlistener = sparkles.event_horizon.io.Listener core.lifetime.move!(sparkles.event_horizon.io.Listener)(ref return scope sparkles.event_horizon.io.Listener source) pure nothrow @nogc @safeExamples
Non-copyable structs can still be moved:
struct S
{
int a = 1;
@disable this(this);
~this() pure nothrow @safe @nogc {}
}
S s1;
s1.a = 2;
S s2 = move(s1);
assert(s1.a == 1);
assert(s2.a == 2);
move((local variable) expected.Expected!(Listener, IoError, NoGcHook) listeninglistening.inout(sparkles.event_horizon.io.Listener) expected.Expected!(sparkles.event_horizon.io.Listener, sparkles.base.io.errors.IoError, sparkles.base.text.errors.NoGcHook).value!()() inout pure nothrow @nogc @property ref @safeReturns the expected value if there is one.
With default Abort hook, it asserts when there is no value.
It calls hook's onAccessEmptyValue otherwise.
It returns T.init when hook doesn't provide onAccessEmptyValue.
value);
scope (exit) (local variable) sparkles.event_horizon.io.Listener listenerlistener.void sparkles.event_horizon.io.Listener.close() nothrow @nogc @trustedclose();
const (local variable) const(ushort) portport = ushort eh_tcp_echo.boundPort(ref sparkles.event_horizon.io.Listener l) @trustedboundPort((local variable) sparkles.event_horizon.io.Listener listenerlistener);
// The server is a joined child, handling one five-byte exchange.
assert((parameter) sparkles.event_horizon.scope_.Scope!(Sched, IoError) scsc.bool sparkles.event_horizon.scope_.Scope!(sparkles.event_horizon.sched.Sched, sparkles.base.io.errors.IoError).spawn(void delegate() body_) nothrow @safeSpawns a child bound to this scope; its defect (escaped Throwable)
feeds the failure policy as Cause.die. body_ is an ordinary
delegate (see Sched.spawn`` — a capturing closure's frame must
outlive this call). Returns whether a fiber slot was accepted; a
rejection still records the scope's ordinary ENOBUFS failure.
spawn({
auto (local variable) expected.Expected!(Stream, IoError, NoGcHook) connconn = (local variable) sparkles.event_horizon.io.Listener listenerlistener.expected.Expected!(Stream, IoError, NoGcHook) sparkles.event_horizon.io.accept(ref sparkles.event_horizon.io.Listener l)Parks until a connection arrives; the result is the connected stream.
accept; // parks until a client arrives
assert((local variable) expected.Expected!(Stream, IoError, NoGcHook) connconn.bool expected.Expected!(sparkles.event_horizon.io.Stream, sparkles.base.io.errors.IoError, sparkles.base.text.errors.NoGcHook).hasValue!()() const pure nothrow @nogc @property @safeChecks if Expected has value
hasValue);
void eh_tcp_echo.echo(sparkles.event_horizon.io.Stream conn)echo((local variable) expected.Expected!(Stream, IoError, NoGcHook) connconn.inout(sparkles.event_horizon.io.Stream) expected.Expected!(sparkles.event_horizon.io.Stream, sparkles.base.io.errors.IoError, sparkles.base.text.errors.NoGcHook).value!()() inout pure nothrow @nogc @property ref @safeReturns the expected value if there is one.
With default Abort hook, it asserts when there is no value.
It calls hook's onAccessEmptyValue otherwise.
It returns T.init when hook doesn't provide onAccessEmptyValue.
value);
}));
// The client, in the same loop.
auto (local variable) expected.Expected!(Stream, IoError, NoGcHook) connectedconnected = (parameter) sparkles.event_horizon.capability.Ctx!(RingClock, RingVfs, RingNet, RingProc) envenv.net.expected.Expected!(Stream, IoError, NoGcHook) sparkles.event_horizon.live.RingNet.connect(sparkles.event_horizon.net.SockAddr to)Creates a TCP socket and connects it to to (parks on the ring).
connect(sparkles.event_horizon.net.SockAddr sparkles.event_horizon.net.ipv4(string dottedQuad, ushort port) pure nothrow @nogc @safeBuilds an IPv4 SockAddr (AF_INET, network byte order).
ipv4("127.0.0.1", (local variable) const(ushort) portport));
assert((local variable) expected.Expected!(Stream, IoError, NoGcHook) connectedconnected.bool expected.Expected!(sparkles.event_horizon.io.Stream, sparkles.base.io.errors.IoError, sparkles.base.text.errors.NoGcHook).hasValue!()() const pure nothrow @nogc @property @safeChecks if Expected has value
hasValue);
auto (local variable) sparkles.event_horizon.io.Stream clientclient = sparkles.event_horizon.io.Stream core.lifetime.move!(sparkles.event_horizon.io.Stream)(ref return scope sparkles.event_horizon.io.Stream source) pure nothrow @nogc @safeExamples
Non-copyable structs can still be moved:
struct S
{
int a = 1;
@disable this(this);
~this() pure nothrow @safe @nogc {}
}
S s1;
s1.a = 2;
S s2 = move(s1);
assert(s1.a == 1);
assert(s2.a == 2);
move((local variable) expected.Expected!(Stream, IoError, NoGcHook) connectedconnected.inout(sparkles.event_horizon.io.Stream) expected.Expected!(sparkles.event_horizon.io.Stream, sparkles.base.io.errors.IoError, sparkles.base.text.errors.NoGcHook).value!()() inout pure nothrow @nogc @property ref @safeReturns the expected value if there is one.
With default Abort hook, it asserts when there is no value.
It calls hook's onAccessEmptyValue otherwise.
It returns T.init when hook doesn't provide onAccessEmptyValue.
value);
scope (exit) (local variable) sparkles.event_horizon.io.Stream clientclient.void sparkles.event_horizon.io.Stream.close() nothrow @nogc @trustedExplicit close (handles are copyable views; exactly one owner
should close). Winsock sockets close via closesocket.
close();
void eh_tcp_echo.sendText(ref sparkles.event_horizon.io.Stream conn, scope const(char)[] bytes)sendText((local variable) sparkles.event_horizon.io.Stream clientclient, "hello");
(alias) sparkles.base.buffer.UniqueBuffer!(ubyte, 64LU) = sparkles.base.buffer.Buffer!(ubyte, 64LU, cast(Storage)cast(ubyte)7u)Small-buffer optimization with a sole owner: inline while the elements fit, heap
when they do not, and copying is disabled.
Disabling copies is what removes the reference count from the grow path — there
is no second owner to consult. Hand a finished one to the shared world with
toShared, which consumes it and transfers any heap block without reallocating.
UniqueBuffer!(ubyte, 64) (local variable) sparkles.base.buffer.Buffer!(ubyte, 64LU, cast(Storage)cast(ubyte)7u) backback;
(alias) object.string = stringstring (local variable) string responseresponse;
while ((local variable) string responseresponse.(field) ulong string.lengthlength < 5)
{
(local variable) sparkles.base.buffer.Buffer!(ubyte, 64LU, cast(Storage)cast(ubyte)7u) backback.void sparkles.base.buffer.Buffer!(ubyte, 64LU, cast(Storage)cast(ubyte)7u).length(ulong newLength) pure nothrow @nogc @property @trustedSets the element count. Growing appends T.init-filled elements (one
storage growth); shrinking drops elements from the back and keeps the
storage, whichever it is (BUF13) — a buffer that has spilled to the
heap stays there until clear or the destructor, so a shrink costs
neither a copy back into the inline slots nor a free.
Output range interface: appends a single element.
length = 64;
auto (local variable) sparkles.event_horizon.io.BufResult!(Buffer!(ubyte, 64LU, cast(Storage)cast(ubyte)7u)) gotgot = (local variable) sparkles.event_horizon.io.Stream clientclient.sparkles.event_horizon.io.BufResult!(Buffer!(ubyte, 64LU, cast(Storage)cast(ubyte)7u)) sparkles.event_horizon.io.recv!(sparkles.base.buffer.Buffer!(ubyte, 64LU, cast(Storage)cast(ubyte)7u))(ref sparkles.event_horizon.io.Stream s, sparkles.base.buffer.Buffer!(ubyte, 64LU, cast(Storage)cast(ubyte)7u) buf) nothrow @safeReceives into the buffer's view.
recv(sparkles.base.buffer.Buffer!(ubyte, 64LU, cast(Storage)cast(ubyte)7u) core.lifetime.move!(sparkles.base.buffer.Buffer!(ubyte, 64LU, cast(Storage)cast(ubyte)7u))(ref return scope sparkles.base.buffer.Buffer!(ubyte, 64LU, cast(Storage)cast(ubyte)7u) source) pure nothrow @nogc @safeExamples
Non-copyable structs can still be moved:
struct S
{
int a = 1;
@disable this(this);
~this() pure nothrow @safe @nogc {}
}
S s1;
s1.a = 2;
S s2 = move(s1);
assert(s1.a == 1);
assert(s2.a == 2);
move((local variable) sparkles.base.buffer.Buffer!(ubyte, 64LU, cast(Storage)cast(ubyte)7u) backback));
(local variable) sparkles.base.buffer.Buffer!(ubyte, 64LU, cast(Storage)cast(ubyte)7u) backback = sparkles.base.buffer.Buffer!(ubyte, 64LU, cast(Storage)cast(ubyte)7u) sparkles.base.buffer.Buffer!(ubyte, 64LU, cast(Storage)cast(ubyte)7u).opAssign(scope sparkles.base.buffer.Buffer!(ubyte, 64LU, cast(Storage)cast(ubyte)7u) rhs) pure nothrow @nogc ref return scope @trustedMove assignment from an rvalue: release current storage, then steal
rhs's storage (no refcount change — ownership transfers). rhs is
neutralized so its destructor frees nothing.
move(sparkles.base.buffer.Buffer!(ubyte, 64LU, cast(Storage)cast(ubyte)7u) sparkles.base.buffer.Buffer!(ubyte, 64LU, cast(Storage)cast(ubyte)7u).opAssign(scope sparkles.base.buffer.Buffer!(ubyte, 64LU, cast(Storage)cast(ubyte)7u) rhs) pure nothrow @nogc ref return scope @trustedMove assignment from an rvalue: release current storage, then steal
rhs's storage (no refcount change — ownership transfers). rhs is
neutralized so its destructor frees nothing.
got.(field) sparkles.base.buffer.Buffer!(ubyte, 64LU, cast(Storage)cast(ubyte)7u) sparkles.event_horizon.io.BufResult!(sparkles.base.buffer.Buffer!(ubyte, 64LU, cast(Storage)cast(ubyte)7u)).bufownership returned — the kernel is done with it
buf);
assert((local variable) sparkles.event_horizon.io.BufResult!(Buffer!(ubyte, 64LU, cast(Storage)cast(ubyte)7u)) gotgot.(field) expected.Expected!(uint, IoError, NoGcHook) sparkles.event_horizon.io.BufResult!(sparkles.base.buffer.Buffer!(ubyte, 64LU, cast(Storage)cast(ubyte)7u)).resbytes transferred, or the error
res.bool expected.Expected!(uint, sparkles.base.io.errors.IoError, sparkles.base.text.errors.NoGcHook).hasValue!()() const pure nothrow @nogc @property @safeChecks if Expected has value
hasValue && (local variable) sparkles.event_horizon.io.BufResult!(Buffer!(ubyte, 64LU, cast(Storage)cast(ubyte)7u)) gotgot.(field) expected.Expected!(uint, IoError, NoGcHook) sparkles.event_horizon.io.BufResult!(sparkles.base.buffer.Buffer!(ubyte, 64LU, cast(Storage)cast(ubyte)7u)).resbytes transferred, or the error
res.inout(uint) expected.Expected!(uint, sparkles.base.io.errors.IoError, sparkles.base.text.errors.NoGcHook).value!()() inout pure nothrow @nogc @property ref @safeReturns the expected value if there is one.
With default Abort hook, it asserts when there is no value.
It calls hook's onAccessEmptyValue otherwise.
It returns T.init when hook doesn't provide onAccessEmptyValue.
value > 0);
(local variable) string responseresponse ~= cast(const(char)[]) (local variable) sparkles.base.buffer.Buffer!(ubyte, 64LU, cast(Storage)cast(ubyte)7u) backback[][0 .. (local variable) sparkles.event_horizon.io.BufResult!(Buffer!(ubyte, 64LU, cast(Storage)cast(ubyte)7u)) gotgot.(field) expected.Expected!(uint, IoError, NoGcHook) sparkles.event_horizon.io.BufResult!(sparkles.base.buffer.Buffer!(ubyte, 64LU, cast(Storage)cast(ubyte)7u)).resbytes transferred, or the error
res.inout(uint) expected.Expected!(uint, sparkles.base.io.errors.IoError, sparkles.base.text.errors.NoGcHook).value!()() inout pure nothrow @nogc @property ref @safeReturns the expected value if there is one.
With default Abort hook, it asserts when there is no value.
It calls hook's onAccessEmptyValue otherwise.
It returns T.init when hook doesn't provide onAccessEmptyValue.
value];
}
assert((local variable) string responseresponse == "hello");
void std.stdio.writeln!(string, string)(string __param_0, string __param_1) @safeEquivalent to write(args, '\n'). Calling writeln without
arguments is valid and just prints a newline to the standard
output.
Example
Reads stdin and writes it to stdout with an argument
counter.
import std.stdio;
void main()
{
string line;
for (size_t count = 0; (line = readln) !is null; count++)
{
writeln("Input ", count, ": ", line);
}
}
writeln("echoed: ", (local variable) string responseresponse);
return 0;
});
assert(run.(field) _error_ run.hasValuehasValue);
}
void void eh_tcp_echo.echo(sparkles.event_horizon.io.Stream conn)echo((struct) sparkles.event_horizon.io.StreamA connected byte-stream socket.
Stream (parameter) sparkles.event_horizon.io.Stream connconn)
{
scope (exit) (parameter) sparkles.event_horizon.io.Stream connconn.void sparkles.event_horizon.io.Stream.close() nothrow @nogc @trustedExplicit close (handles are copyable views; exactly one owner
should close). Winsock sockets close via closesocket.
close();
(alias) sparkles.base.buffer.UniqueBuffer!(ubyte, 4096LU) = sparkles.base.buffer.Buffer!(ubyte, 4096LU, cast(Storage)cast(ubyte)7u)Small-buffer optimization with a sole owner: inline while the elements fit, heap
when they do not, and copying is disabled.
Disabling copies is what removes the reference count from the grow path — there
is no second owner to consult. Hand a finished one to the shared world with
toShared, which consumes it and transfers any heap block without reallocating.
UniqueBuffer!(ubyte, 4096) (local variable) sparkles.base.buffer.Buffer!(ubyte, 4096LU, cast(Storage)cast(ubyte)7u) bufbuf;
(alias) object.size_t = ulongsize_t (local variable) ulong receivedreceived;
while ((local variable) ulong receivedreceived < 5)
{
(local variable) sparkles.base.buffer.Buffer!(ubyte, 4096LU, cast(Storage)cast(ubyte)7u) bufbuf.void sparkles.base.buffer.Buffer!(ubyte, 4096LU, cast(Storage)cast(ubyte)7u).length(ulong newLength) pure nothrow @nogc @property @trustedSets the element count. Growing appends T.init-filled elements (one
storage growth); shrinking drops elements from the back and keeps the
storage, whichever it is (BUF13) — a buffer that has spilled to the
heap stays there until clear or the destructor, so a shrink costs
neither a copy back into the inline slots nor a free.
Output range interface: appends a single element.
length = 4096;
auto (local variable) sparkles.event_horizon.io.BufResult!(Buffer!(ubyte, 4096LU, cast(Storage)cast(ubyte)7u)) rr = (parameter) sparkles.event_horizon.io.Stream connconn.sparkles.event_horizon.io.BufResult!(Buffer!(ubyte, 4096LU, cast(Storage)cast(ubyte)7u)) sparkles.event_horizon.io.recv!(sparkles.base.buffer.Buffer!(ubyte, 4096LU, cast(Storage)cast(ubyte)7u))(ref sparkles.event_horizon.io.Stream s, sparkles.base.buffer.Buffer!(ubyte, 4096LU, cast(Storage)cast(ubyte)7u) buf) nothrow @safeReceives into the buffer's view.
recv(sparkles.base.buffer.Buffer!(ubyte, 4096LU, cast(Storage)cast(ubyte)7u) core.lifetime.move!(sparkles.base.buffer.Buffer!(ubyte, 4096LU, cast(Storage)cast(ubyte)7u))(ref return scope sparkles.base.buffer.Buffer!(ubyte, 4096LU, cast(Storage)cast(ubyte)7u) source) pure nothrow @nogc @safeExamples
Non-copyable structs can still be moved:
struct S
{
int a = 1;
@disable this(this);
~this() pure nothrow @safe @nogc {}
}
S s1;
s1.a = 2;
S s2 = move(s1);
assert(s1.a == 1);
assert(s2.a == 2);
move((local variable) sparkles.base.buffer.Buffer!(ubyte, 4096LU, cast(Storage)cast(ubyte)7u) bufbuf));
(local variable) sparkles.base.buffer.Buffer!(ubyte, 4096LU, cast(Storage)cast(ubyte)7u) bufbuf = sparkles.base.buffer.Buffer!(ubyte, 4096LU, cast(Storage)cast(ubyte)7u) sparkles.base.buffer.Buffer!(ubyte, 4096LU, cast(Storage)cast(ubyte)7u).opAssign(scope sparkles.base.buffer.Buffer!(ubyte, 4096LU, cast(Storage)cast(ubyte)7u) rhs) pure nothrow @nogc ref return scope @trustedMove assignment from an rvalue: release current storage, then steal
rhs's storage (no refcount change — ownership transfers). rhs is
neutralized so its destructor frees nothing.
move(sparkles.base.buffer.Buffer!(ubyte, 4096LU, cast(Storage)cast(ubyte)7u) sparkles.base.buffer.Buffer!(ubyte, 4096LU, cast(Storage)cast(ubyte)7u).opAssign(scope sparkles.base.buffer.Buffer!(ubyte, 4096LU, cast(Storage)cast(ubyte)7u) rhs) pure nothrow @nogc ref return scope @trustedMove assignment from an rvalue: release current storage, then steal
rhs's storage (no refcount change — ownership transfers). rhs is
neutralized so its destructor frees nothing.
r.(field) sparkles.base.buffer.Buffer!(ubyte, 4096LU, cast(Storage)cast(ubyte)7u) sparkles.event_horizon.io.BufResult!(sparkles.base.buffer.Buffer!(ubyte, 4096LU, cast(Storage)cast(ubyte)7u)).bufownership returned — the kernel is done with it
buf);
assert((local variable) sparkles.event_horizon.io.BufResult!(Buffer!(ubyte, 4096LU, cast(Storage)cast(ubyte)7u)) rr.(field) expected.Expected!(uint, IoError, NoGcHook) sparkles.event_horizon.io.BufResult!(sparkles.base.buffer.Buffer!(ubyte, 4096LU, cast(Storage)cast(ubyte)7u)).resbytes transferred, or the error
res.bool expected.Expected!(uint, sparkles.base.io.errors.IoError, sparkles.base.text.errors.NoGcHook).hasValue!()() const pure nothrow @nogc @property @safeChecks if Expected has value
hasValue && (local variable) sparkles.event_horizon.io.BufResult!(Buffer!(ubyte, 4096LU, cast(Storage)cast(ubyte)7u)) rr.(field) expected.Expected!(uint, IoError, NoGcHook) sparkles.event_horizon.io.BufResult!(sparkles.base.buffer.Buffer!(ubyte, 4096LU, cast(Storage)cast(ubyte)7u)).resbytes transferred, or the error
res.inout(uint) expected.Expected!(uint, sparkles.base.io.errors.IoError, sparkles.base.text.errors.NoGcHook).value!()() inout pure nothrow @nogc @property ref @safeReturns the expected value if there is one.
With default Abort hook, it asserts when there is no value.
It calls hook's onAccessEmptyValue otherwise.
It returns T.init when hook doesn't provide onAccessEmptyValue.
value > 0);
(local variable) ulong receivedreceived += (local variable) sparkles.event_horizon.io.BufResult!(Buffer!(ubyte, 4096LU, cast(Storage)cast(ubyte)7u)) rr.(field) expected.Expected!(uint, IoError, NoGcHook) sparkles.event_horizon.io.BufResult!(sparkles.base.buffer.Buffer!(ubyte, 4096LU, cast(Storage)cast(ubyte)7u)).resbytes transferred, or the error
res.inout(uint) expected.Expected!(uint, sparkles.base.io.errors.IoError, sparkles.base.text.errors.NoGcHook).value!()() inout pure nothrow @nogc @property ref @safeReturns the expected value if there is one.
With default Abort hook, it asserts when there is no value.
It calls hook's onAccessEmptyValue otherwise.
It returns T.init when hook doesn't provide onAccessEmptyValue.
value;
void eh_tcp_echo.sendText(ref sparkles.event_horizon.io.Stream conn, scope const(char)[] bytes)sendText((parameter) sparkles.event_horizon.io.Stream connconn, cast(const(char)[]) (local variable) sparkles.base.buffer.Buffer!(ubyte, 4096LU, cast(Storage)cast(ubyte)7u) bufbuf[][0 .. (local variable) sparkles.event_horizon.io.BufResult!(Buffer!(ubyte, 4096LU, cast(Storage)cast(ubyte)7u)) rr.(field) expected.Expected!(uint, IoError, NoGcHook) sparkles.event_horizon.io.BufResult!(sparkles.base.buffer.Buffer!(ubyte, 4096LU, cast(Storage)cast(ubyte)7u)).resbytes transferred, or the error
res.inout(uint) expected.Expected!(uint, sparkles.base.io.errors.IoError, sparkles.base.text.errors.NoGcHook).value!()() inout pure nothrow @nogc @property ref @safeReturns the expected value if there is one.
With default Abort hook, it asserts when there is no value.
It calls hook's onAccessEmptyValue otherwise.
It returns T.init when hook doesn't provide onAccessEmptyValue.
value]);
}
}
// Copies the unsent suffix into an owned buffer on each attempt. This is a
// small correctness example, not a claim of zero-copy networking.
void void eh_tcp_echo.sendText(ref sparkles.event_horizon.io.Stream conn, scope const(char)[] bytes)sendText(ref (struct) sparkles.event_horizon.io.StreamA connected byte-stream socket.
Stream (parameter) sparkles.event_horizon.io.Stream connconn, scope const(char)[] (parameter) const(char)[] bytesbytes)
{
(alias) object.size_t = ulongsize_t (local variable) ulong offsetoffset;
while ((local variable) ulong offsetoffset < (parameter) const(char)[] bytesbytes.(field) ulong const(char)[].lengthlength)
{
(alias) sparkles.base.buffer.UniqueBuffer!(ubyte, 64LU) = sparkles.base.buffer.Buffer!(ubyte, 64LU, cast(Storage)cast(ubyte)7u)Small-buffer optimization with a sole owner: inline while the elements fit, heap
when they do not, and copying is disabled.
Disabling copies is what removes the reference count from the grow path — there
is no second owner to consult. Hand a finished one to the shared world with
toShared, which consumes it and transfers any heap block without reallocating.
UniqueBuffer!(ubyte, 64) (local variable) sparkles.base.buffer.Buffer!(ubyte, 64LU, cast(Storage)cast(ubyte)7u) bufbuf;
(local variable) sparkles.base.buffer.Buffer!(ubyte, 64LU, cast(Storage)cast(ubyte)7u) bufbuf ~= cast(const(ubyte)[]) (parameter) const(char)[] bytesbytes[(local variable) ulong offsetoffset .. $];
auto (local variable) sparkles.event_horizon.io.BufResult!(Buffer!(ubyte, 64LU, cast(Storage)cast(ubyte)7u)) sentsent = (parameter) sparkles.event_horizon.io.Stream connconn.sparkles.event_horizon.io.BufResult!(Buffer!(ubyte, 64LU, cast(Storage)cast(ubyte)7u)) sparkles.event_horizon.io.send!(sparkles.base.buffer.Buffer!(ubyte, 64LU, cast(Storage)cast(ubyte)7u))(ref sparkles.event_horizon.io.Stream s, sparkles.base.buffer.Buffer!(ubyte, 64LU, cast(Storage)cast(ubyte)7u) buf) nothrow @safeSends the buffer's view.
send(sparkles.base.buffer.Buffer!(ubyte, 64LU, cast(Storage)cast(ubyte)7u) core.lifetime.move!(sparkles.base.buffer.Buffer!(ubyte, 64LU, cast(Storage)cast(ubyte)7u))(ref return scope sparkles.base.buffer.Buffer!(ubyte, 64LU, cast(Storage)cast(ubyte)7u) source) pure nothrow @nogc @safeExamples
Non-copyable structs can still be moved:
struct S
{
int a = 1;
@disable this(this);
~this() pure nothrow @safe @nogc {}
}
S s1;
s1.a = 2;
S s2 = move(s1);
assert(s1.a == 1);
assert(s2.a == 2);
move((local variable) sparkles.base.buffer.Buffer!(ubyte, 64LU, cast(Storage)cast(ubyte)7u) bufbuf));
assert((local variable) sparkles.event_horizon.io.BufResult!(Buffer!(ubyte, 64LU, cast(Storage)cast(ubyte)7u)) sentsent.(field) expected.Expected!(uint, IoError, NoGcHook) sparkles.event_horizon.io.BufResult!(sparkles.base.buffer.Buffer!(ubyte, 64LU, cast(Storage)cast(ubyte)7u)).resbytes transferred, or the error
res.bool expected.Expected!(uint, sparkles.base.io.errors.IoError, sparkles.base.text.errors.NoGcHook).hasValue!()() const pure nothrow @nogc @property @safeChecks if Expected has value
hasValue && (local variable) sparkles.event_horizon.io.BufResult!(Buffer!(ubyte, 64LU, cast(Storage)cast(ubyte)7u)) sentsent.(field) expected.Expected!(uint, IoError, NoGcHook) sparkles.event_horizon.io.BufResult!(sparkles.base.buffer.Buffer!(ubyte, 64LU, cast(Storage)cast(ubyte)7u)).resbytes transferred, or the error
res.inout(uint) expected.Expected!(uint, sparkles.base.io.errors.IoError, sparkles.base.text.errors.NoGcHook).value!()() inout pure nothrow @nogc @property ref @safeReturns the expected value if there is one.
With default Abort hook, it asserts when there is no value.
It calls hook's onAccessEmptyValue otherwise.
It returns T.init when hook doesn't provide onAccessEmptyValue.
value > 0);
(local variable) ulong offsetoffset += (local variable) sparkles.event_horizon.io.BufResult!(Buffer!(ubyte, 64LU, cast(Storage)cast(ubyte)7u)) sentsent.(field) expected.Expected!(uint, IoError, NoGcHook) sparkles.event_horizon.io.BufResult!(sparkles.base.buffer.Buffer!(ubyte, 64LU, cast(Storage)cast(ubyte)7u)).resbytes transferred, or the error
res.inout(uint) expected.Expected!(uint, sparkles.base.io.errors.IoError, sparkles.base.text.errors.NoGcHook).value!()() inout pure nothrow @nogc @property ref @safeReturns the expected value if there is one.
With default Abort hook, it asserts when there is no value.
It calls hook's onAccessEmptyValue otherwise.
It returns T.init when hook doesn't provide onAccessEmptyValue.
value;
}
}
ushort ushort eh_tcp_echo.boundPort(ref sparkles.event_horizon.io.Listener l) @trustedboundPort(ref (struct) sparkles.event_horizon.io.ListenerA listening socket; accept yields Streams.
Listener (parameter) sparkles.event_horizon.io.Listener ll) @trusted
{
import (package) corecore.(package) core.syssys.(package) core.sys.posixposix.(package) core.sys.posix.arpaarpa.(module) core.sys.posix.arpa.inetD header file for POSIX.
inet : (alias) ntohs = ushort core.sys.posix.arpa.inet.ntohs(ushort) pure nothrow @nogc @trustedntohs;
import (package) corecore.(package) core.syssys.(package) core.sys.posixposix.(package) core.sys.posix.netinetnetinet.(module) core.sys.posix.netinet.in_D header file for POSIX.
in_ : (struct) core.sys.posix.netinet.in_.sockaddr_insockaddr_in;
import (package) corecore.(package) core.syssys.(package) core.sys.posixposix.(package) core.sys.posix.syssys.(module) core.sys.posix.sys.socketD header file for POSIX.
socket : (alias) getsockname = int core.sys.posix.sys.socket.getsockname(int, scope core.sys.posix.sys.socket.sockaddr*, scope uint*) nothrow @nogcgetsockname, (struct) core.sys.posix.sys.socket.sockaddrsockaddr, socklen_t;
(struct) core.sys.posix.netinet.in_.sockaddr_insockaddr_in (local variable) core.sys.posix.netinet.in_.sockaddr_in aa;
socklen_t (local variable) uint lenlen = (local variable) core.sys.posix.netinet.in_.sockaddr_in aa.(constant) ulong core.sys.posix.netinet.in_.sockaddr_in.sizeof = 16LUsizeof;
assert(int core.sys.posix.sys.socket.getsockname(int, scope core.sys.posix.sys.socket.sockaddr*, scope uint*) nothrow @nogcgetsockname((parameter) sparkles.event_horizon.io.Listener ll.(field) int sparkles.event_horizon.io.Listener.fdfd, cast((struct) core.sys.posix.sys.socket.sockaddrsockaddr*) &(local variable) core.sys.posix.netinet.in_.sockaddr_in aa, &(local variable) uint lenlen) == 0);
return ushort core.sys.posix.arpa.inet.ntohs(ushort) pure nothrow @nogc @trustedntohs((local variable) core.sys.posix.netinet.in_.sockaddr_in aa.(field) ushort core.sys.posix.netinet.in_.sockaddr_in.sin_portsin_port);
}