pipe

tape
import pipe from "pipe";
import io from "io";
import time from "time";

fn main() -> i32 {
    var l: pipe.Listener = pipe.listen("director") or { return 1; };
    // another program: pipe.connect("director")
    var pane: pipe.Stream = l.accept(time.seconds(10)) or {
        io.println("no pane: {err}");
        return 2;
    };
    pane.write_all("run step 1\n") or { return 3; };
    let reply: ?string = pane.read_line(time.seconds(5)) or {
        io.println("no answer: {err}");     // TimedOut
        return 4;
    };
    if (reply != null) { io.println("pane says {reply!}"); }
    pane.close();
    l.close();
    return 0;
}

pipe connects programs on the same machine. One program listens on a name; others connect to it; each connection is a stream of bytes both ways. On Windows it is a named pipe, \\.\pipe\<name>, which any program can also open as a file. On Linux and macOS it is a Unix domain socket, a socket file in the temporary directory. Not available on Uusi.

Listening

FunctionDoes
listen(name) -> Listener or io.IoErrorListen on name
l.accept(timeout) -> Stream or io.IoErrorThe next client’s connection; TimedOut after timeout
l.path() -> stringWhere the pipe is
l.close()Stop listening (removes the socket file on Linux and macOS)

listen fails with AddrInUse when another program listens on the name. A socket file left behind by a program that ended without closing is replaced. When accept times out the listener keeps listening: call it again. Leave the timeout out to wait without limit.

Connecting

FunctionDoes
connect(name, timeout) -> Stream or io.IoErrorConnect to the program listening on name
path(name) -> stringWhere the pipe called name is: \\.\pipe\<name>, or a file in the temporary directory

connect fails with NotFound when nothing is there (ConnectionRefused on Linux and macOS for a socket file no one listens on). On Windows it waits at most timeout while the pipe is busy. A name with a path separator in it is used as a path as it is.

Streams

FunctionDoes
s.read(buf, timeout) -> i64 or io.IoErrorUp to buf.len bytes; 0 once the other end has closed
s.read_line(timeout) -> ?string or io.IoErrorThe next line without its newline; null at the end
s.write(data) -> i64 or io.IoError / s.write_all(data)Write some / all of data
s.reader() -> io.Reader / s.writer() -> io.WriterFor read_all, BufReader, BufWriter, fmt (no timeout)
s.close()Close this end: the other end reads the end

Every timeout is an optional time.Duration: left out, the call waits as long as it takes; when it passes, the call fails with TimedOut. read_line’s timeout is for the whole line, and a line it timed out on is kept: the next call carries on with it. A write fails with BrokenPipe once the other end has closed.

Last modified: