io
Every byte source implements Read and every byte sink implements Write. Because both traits carry substantial defaults, an implementation only has to supply one method to get the whole convenience surface — read_line, read_to_string, write, and the rest — for free. IoError is the failure channel throughout.
public module io::error;
public module io::fd;
public module io::traits;
public module io::stdio;
public module io::buf;
public module io::cursor;
| File | What it holds | Import |
|---|---|---|
traits | Read, Write, Seek, and the async AsyncRead / AsyncWrite / AsyncTransport | import std::io::traits; |
stdio | Stdin, Stdout, Stderr and their lock guards | import std::io::stdio; |
buf | BufReader, BufWriter, LineWriter, and the async BufStream | import std::io::buf; |
cursor | Cursor, an in-memory Read + Write + Seek | import std::io::cursor; |
error | IoError, IoErrorKind, the errno constants | import std::io::error; |
fd | read_fd, write_fd, close_fd | import std::io::fd; |
There is no buffering by default anywhere in this module: the standard streams and File translate to raw read(2) / write(2) calls. Compose it explicitly with the adapters in buf when you want it.
public function name() { ... }
public:Visible to any module that imports this one - the default for top-level items and for struct fields, so it is mostly written to be explicit. public: opens a visibility block that groups the members after it.
public module collections::array;In a directory's _module.cryo aggregator, lists a submodule and whether it is public. Importing the directory's namespace sees only the modules declared public here.
namespace std::io::traits;The byte-source and byte-sink traits, blocking and non-blocking.
module pagenamespace std::io::cursor;Cursor: an in-memory byte buffer that is Read, Write, and Seek.
type trait Read {
read(mut &this, buffer: u8*, length: u64) -> Result<u64, IoError>;
read_all(mut &this, buffer: u8*, length: u64) -> Result<u64, IoError>;
read_byte(mut &this) -> Result<Option<u8>, IoError>;
read_char(mut &this) -> Result<Option<u32>, IoError>;
read_until(mut &this, delimiter: u8, out: mut &Array<u8>) -> Result<u64, IoError>;
read_exact(mut &this, buffer: u8*, length: u64) -> Result<(), IoError>;
read_to_end(mut &this, out: mut &Array<u8>) -> Result<u64, IoError>;
read_to_string(mut &this, out: mut &String) -> Result<u64, IoError>;
read_line(mut &this, out: mut &String) -> Result<u64, IoError>;
}type trait Write {
write_some(mut &this, bytes: Slice<u8>) -> Result<u64, IoError>;
flush(mut &this) -> Result<(), IoError>;
write<T>(mut &this, data: T) -> Result<(), IoError>;
}type struct IoError {
kind: IoErrorKind;
os_code: i32;
}type trait Seek {
seek(mut &this, from: SeekFrom) -> Result<u64, IoError>;
stream_position(mut &this) -> Result<u64, IoError>;
rewind(mut &this) -> Result<(), IoError>;
}A byte stream whose read/write cursor can be repositioned. Absolute positions are u64 offsets from the start; every seek returns the resulting absolute position.
type trait AsyncRead {
async fill(mut &this) -> Result<u64, IoError>;
buffered(&this) -> Slice<u8>;
consume(mut &this, count: u64) -> void;
scan_for(&this, delimiter: u8, from: u64) -> u64;
take_front(mut &this, count: u64) -> Result<Array<u8>, IoError>;
async ensure(mut &this, count: u64) -> Result<(), IoError>;
async read_exact(mut &this, count: u64) -> Result<Array<u8>, IoError>;
async read_some(mut &this, limit: u64) -> Result<Array<u8>, IoError>;
async read_until(mut &this, delimiter: u8, limit: u64) -> Result<Array<u8>, IoError>;
async read_line(mut &this, limit: u64) -> Result<String, IoError>;
// … 1 more
}A byte source that buffers what it reads inside itself.
std::io::traitstype trait AsyncWrite {
pending(mut &this) -> Array<u8>*;
async flush(mut &this) -> Result<(), IoError>;
queue<T>(mut &this, data: T) -> Result<(), IoError>;
async send<T>(mut &this, data: T) -> Result<(), IoError>;
}A byte sink that buffers what it is given until told to send it.
std::io::traitstype trait AsyncTransport {
async read_into(mut &this, buf: Array<u8>) -> Transfer;
async write_from(mut &this, buf: Array<u8>) -> Transfer;
}One raw, unbuffered async byte channel: what BufStream<S> needs of a transport, and nothing more.
import a::b;
import a::b::{ X, Y };
import a::b as c;
import a::b::*;Brings a module, or selected items from it, into scope. One path per declaration: use the brace form for several items, as to alias, and * for everything public (prefer the brace form; wildcards invite name collisions).
type struct Stdin {}Handle to process standard input. Construction is free; all instances dispatch to file descriptor 0. Unbuffered: a line read that needs minimum syscalls should wrap this in a BufReader<Stdin> from io::buf.
type struct Stdout {}Handle to process standard output. Unbuffered; wrap in LineWriter<Stdout> or BufWriter<Stdout> from io::buf for the common "coalesce many small writes" case.
type struct Stderr {}Handle to process standard error. Unbuffered by convention so diagnostics appear immediately; do **not** wrap in BufWriter unless you also guarantee a flush on every path that might panic or exit.
type struct BufReader<R> where R: Read {
reader: R*;
buffer: u8*;
capacity: u64;
position: u64;
filled: u64;
}Pulls from R in buffer-sized chunks and serves reads from the buffer. Transforms a stream of small reads into a few large ones and makes read_line fast: no per-byte syscall.
type struct BufWriter<W> where W: Write {
writer: W*;
buffer: u8*;
capacity: u64;
length: u64;
}Coalesces writes destined for W into larger flushes. The inner writer is borrowed via pointer; the caller owns it and drops it.
type struct LineWriter<W> {
inner: BufWriter<W>;
}A BufWriter that flushes after any write containing a \n. Appropriate for interactive stdout on a TTY, where "the user saw the line as soon as it was emitted" matters more than coalescing.
type struct BufStream<S> {
inner: S;
rbuf: Array<u8>;
rpos: u64;
scratch: Array<u8>;
wbuf: Array<u8>;
}type struct Cursor {
buffer: Array<u8>;
pos: u64;
}An in-memory Read + Write + Seek byte buffer. Owns its Array<u8>; drop releases it (or move it out with into_inner first).
type enum IoErrorKind {
NotFound;
PermissionDenied;
AlreadyExists;
ConnectionRefused;
ConnectionReset;
ConnectionAborted;
NotConnected;
AddrInUse;
AddrNotAvailable;
BrokenPipe;
// … 10 more
}function read(fd: i32, buffer: u8*, count: u64) -> i64POSIX-shaped read over CRT _read. The count is clamped to the CRT's INT_MAX request ceiling - a short read is legal under the POSIX contract, so callers loop as they already must.
function write(fd: i32, buffer: u8*, count: u64) -> i64POSIX-shaped write over CRT _write; same clamp, short writes legal.