peekable

Crates.iopeekable
lib.rspeekable
version0.4.1
created_at2024-01-24 18:18:18.280058+00
updated_at2025-06-29 19:33:47.788937+00
descriptionPeekable reader and async reader, which enhance your network programming experience.
homepagehttps://github.com/al8n/peekable
repositoryhttps://github.com/al8n/peekable
max_upload_size
id1112705
size147,735
Al Liu (al8n)

documentation

https://docs.rs/peekable

README

Peekable

Peekable reader and async reader, which enhance your network programming experience.

github LoC Build codecov

docs.rs crates.io crates.io license

Introduction

In network programming, applications frequently need to inspect incoming data before fully consuming it. Common patterns include reading message type indicators, parsing length-prefixed headers, or implementing protocol detection. However, current peek solutions have significant limitations:

System call-based approaches like std::net::TcpStream::peek and tokio::net::TcpStream::peek directly invoke system calls for each peek operation. While functionally correct, these methods impose unnecessary overhead since system calls are expensive operations that should be minimized in performance-critical network code.

Buffered reader workarounds involve wrapping streams with BufReader and using methods like fill_buf() and buffer() to simulate peeking behavior. This approach is cumbersome and inefficient—BufReader uses a heap-allocated Vec<u8> as its internal buffer, which is overkill for typical peek scenarios where you only need to examine a few bytes (often 1-8 bytes for headers or type tags).

peekable provides a better solution: a lightweight, efficient peek implementation for both synchronous and asynchronous readers.

Installation

  • Std

    [dependencies]
    peekable = "0.4"
    
  • Tokio I/O

    [dependencies]
    peekable = { version = "0.4", features = ["tokio"] }
    
  • Futures I/O

    [dependencies]
    peekable = { version = "0.4", features = ["future"] }
    

Examples

  • Std

    use std::{net::TcpStream, io::Read};
    use peekable::Peekable;
    
    let conn = TcpStream::connect("127.0.0.1:8080").unwrap();
    let mut peekable = Peekable::from(conn);
    
    let mut peeked = [0; 16];
    peekable.peek_exact(&mut peeked).unwrap();
    
    let mut readed = [0; 16];
    peekable.read_exact(&mut readed).unwrap();
    
    assert_eq!(peeked, readed);
    
  • Tokio I/O

    use tokio::{net::TcpStream, io::AsyncReadExt};
    use peekable::tokio::AsyncPeekable;
    
    let conn = TcpStream::connect("127.0.0.1:8080").await.unwrap();
    let mut peekable = AsyncPeekable::from(conn);
    
    let mut peeked = [0; 16];
    peekable.peek_exact(&mut peeked).await.unwrap();
    
    let mut readed = [0; 16];
    peekable.read_exact(&mut readed).await.unwrap();
    
    assert_eq!(peeked, readed);
    
  • Futures I/O

    use async_std::net::TcpStream;
    use futures::AsyncReadExt;
    use peekable::future::AsyncPeekable;
    
    let conn = TcpStream::connect("127.0.0.1:8080").await.unwrap();
    let mut peekable = AsyncPeekable::from(conn);
    
    let mut peeked = [0; 16];
    peekable.peek_exact(&mut peeked).await.unwrap();
    
    let mut readed = [0; 16];
    peekable.read_exact(&mut readed).await.unwrap();
    
    assert_eq!(peeked, readed);
    

License

peekable is under the terms of both the MIT license and the Apache License (Version 2.0).

See LICENSE-APACHE, LICENSE-MIT for details.

Copyright (c) 2024 Al Liu.

Commit count: 16

cargo fmt