Crates.io | peekable |
lib.rs | peekable |
version | 0.4.1 |
created_at | 2024-01-24 18:18:18.280058+00 |
updated_at | 2025-06-29 19:33:47.788937+00 |
description | Peekable reader and async reader, which enhance your network programming experience. |
homepage | https://github.com/al8n/peekable |
repository | https://github.com/al8n/peekable |
max_upload_size | |
id | 1112705 |
size | 147,735 |
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.
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"] }
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);
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.