Essential Standard Traits

Seek

The Seek trait in std::io moves a byte cursor to an arbitrary offset within a stream, enabling random-access reads and writes in files and in-memory buffers.

Trait Definition and SeekFrom

pub enum SeekFrom {
    Start(u64),
    End(i64),
    Current(i64),
}

pub trait Seek {
    fn seek(&mut self, pos: SeekFrom) -> std::io::Result<u64>;

    // Provided methods:
    fn rewind(&mut self) -> std::io::Result<()>;
    fn stream_position(&mut self) -> std::io::Result<u64>;
}

Calling seek(&mut self, pos) repositions the stream cursor and returns Ok(new_position) measured in bytes from the start of the stream.

Variant / Method Behavior
SeekFrom::Start(n) Sets cursor to absolute byte offset n from the beginning of the stream
SeekFrom::Current(delta) Moves cursor by signed delta bytes relative to its current position
SeekFrom::End(delta) Moves cursor by signed delta bytes relative to the end of the stream
.rewind() Equivalent to .seek(SeekFrom::Start(0))
.stream_position() Equivalent to .seek(SeekFrom::Current(0)); returns current byte offset

Random-Access I/O with std::io::Cursor

While network sockets (TcpStream) and pipes are sequential and do not implement Seek, std::fs::File and std::io::Cursor<T> implement Seek alongside Read and Write:

use std::io::{self, Cursor, Read, Seek, SeekFrom, Write};

fn main() -> io::Result<()> {
    let mut stream = Cursor::new(Vec::new());

    stream.write_all(b"HEADER:0000:PAYLOAD")?;

    // Jump to byte offset 7 to overwrite the 4-byte length field:
    stream.seek(SeekFrom::Start(7))?;
    stream.write_all(b"0007")?;

    // Read the last 7 bytes using SeekFrom::End:
    stream.seek(SeekFrom::End(-7))?;
    let mut tail = String::new();
    stream.read_to_string(&mut tail)?;

    // Rewind to the start to read the entire modified stream:
    stream.rewind()?;
    let mut full = String::new();
    stream.read_to_string(&mut full)?;

    println!("Tail: {tail}");
    println!("Full: {full}");
    Ok(())
}
Tail: PAYLOAD
Full: HEADER:0007:PAYLOAD

Combining Read + Seek in Binary Parsers

Formats with footer indexes (such as ZIP archives or Parquet files) typically bound their input stream by R: Read + Seek so the parser can seek to the end of the stream (SeekFrom::End), read the central directory offset, and then seek directly to specific compressed entries without scanning the entire file sequentially.