Crates.io | fixed-buffer |
lib.rs | fixed-buffer |
version | 1.0.0 |
source | src |
created_at | 2020-10-27 05:18:36.551941 |
updated_at | 2024-10-21 06:34:21.873568 |
description | Fixed-size buffers for network protocol parsers |
homepage | |
repository | https://gitlab.com/leonhard-llc/fixed-buffer-rs |
max_upload_size | |
id | 305855 |
size | 87,851 |
This is a Rust library with fixed-size buffers, useful for network protocol parsers and file parsers.
forbid(unsafe_code)
std
async-std-feature
, futures-io
, smol-feature
, or tokio
.shift()
periodically
to move unread bytes to the front of the buffer.Read and handle requests from a remote client:
use fixed_buffer::{deframe_line, FixedBuf};
use std::io::Error;
use std::net::TcpStream;
fn handle_conn(mut tcp_stream: TcpStream) -> Result<(), Error> {
let mut buf: FixedBuf<4096> = FixedBuf::new();
loop {
// Read a line
// and leave leftover bytes in `buf`.
let line_bytes = match buf.read_frame(
&mut tcp_stream, deframe_line)? {
Some(line_bytes) => line_bytes,
None => return Ok(()),
};
let request = Request::parse(line_bytes)?;
handle_request(request)?;
}
}
For a complete example, see
tests/server.rs
.
Read and process records:
use fixed_buffer::FixedBuf;
use std::io::{Error, ErrorKind, Read};
use std::net::TcpStream;
fn try_process_record(b: &[u8]) -> Result<usize, Error> {
if b.len() < 2 {
return Ok(0);
}
if b.starts_with("ab".as_bytes()) {
println!("found record");
Ok(2)
} else {
Err(Error::new(ErrorKind::InvalidData, "bad record"))
}
}
fn read_and_process<R: Read>(mut input: R) -> Result<(), Error> {
let mut buf: FixedBuf<1024> = FixedBuf::new();
loop {
// Read a chunk into the buffer.
if buf.copy_once_from(&mut input)? == 0 {
return if buf.len() == 0 {
// EOF at record boundary
Ok(())
} else {
// EOF in the middle of a record
Err(Error::from(
ErrorKind::UnexpectedEof))
};
}
// Process records in the buffer.
loop {
let num_to_consume =
try_process_record(buf.readable())?;
if num_to_consume == 0 {
break;
}
buf.try_read_exact(num_to_consume).unwrap();
}
// Shift data in the buffer to free up
// space at the end for writing.
buf.shift();
}
}
#
The From<&[u8; SIZE]>
implementation is useful in tests. Example:
use core::convert::From;
assert_eq!(3, FixedBuf::from(b"abc").len());
Metric output format: x/y
x = unsafe code used by the build
y = total unsafe code found in the crate
Symbols:
🔒 = No `unsafe` usage found, declares #![forbid(unsafe_code)]
❓ = No `unsafe` usage found, missing #![forbid(unsafe_code)]
☢️ = `unsafe` usage found
Functions Expressions Impls Traits Methods Dependency
0/0 0/0 0/0 0/0 0/0 🔒 fixed-buffer 1.0.0
0/0 0/0 0/0 0/0 0/0 ❓ ├── futures-io 0.3.31
0/25 0/1782 0/102 0/1 0/69 ❓ └── tokio 1.12.0
0/17 0/607 0/13 0/1 0/19 ❓ ├── bytes 1.1.0
0/90 0/596 0/2 0/0 0/69 ❓ ├── libc 0.2.161
0/37 0/2025 0/0 0/0 0/16 ❓ ├── memchr 2.4.1
0/90 0/596 0/2 0/0 0/69 ❓ │ └── libc 0.2.161
0/0 0/72 0/0 0/0 0/0 ❓ ├── num_cpus 1.13.1
0/90 0/596 0/2 0/0 0/69 ❓ │ └── libc 0.2.161
0/1 0/85 0/6 0/0 0/3 ❓ ├── once_cell 1.8.0
0/0 0/191 0/0 0/0 0/2 ❓ ├── pin-project-lite 0.2.14
0/0 0/12 0/0 0/0 0/0 🔒 ├── signal-hook-registry 1.4.0
0/90 0/596 0/2 0/0 0/69 ❓ │ └── libc 0.2.161
0/0 0/0 0/0 0/0 0/0 ❓ └── tokio-macros 1.7.0
0/0 0/12 0/0 0/0 0/3 ❓ ├── proc-macro2 1.0.36
0/0 0/0 0/0 0/0 0/0 🔒 │ └── unicode-xid 0.2.2
0/0 0/0 0/0 0/0 0/0 ❓ ├── quote 1.0.16
0/0 0/12 0/0 0/0 0/3 ❓ │ └── proc-macro2 1.0.36
0/0 0/47 0/3 0/0 0/2 ❓ └── syn 1.0.89
0/0 0/12 0/0 0/0 0/3 ❓ ├── proc-macro2 1.0.36
0/0 0/0 0/0 0/0 0/0 ❓ ├── quote 1.0.16
0/0 0/0 0/0 0/0 0/0 🔒 └── unicode-xid 0.2.2
0/170 0/5429 0/126 0/2 0/183
bytes
, lots of unsafe
buf_redux
, circular buffer support, updated in 2019std::io::BufReader
std::io::BufWriter
static-buffer
, updated in 2016block-buffer
, for processing fixed-length blocks of data, some unsafe
arrayvec
, vector with fixed capacity, some unsafe
From<&[u8; SIZE]>
, FixedBuffer::from(b"x")
ReadWriteChain
and ReadWriteTake
to new
read-write-ext
crate.From<[u8; SIZE]>
, FixedBuffer::from([0])
write_bytes
to take AsRef<[u8]>
try_read_exact
to read_and_copy_exact
.try_read_bytes
to try_read_exact
.empty
, filled
, read_byte
, read_bytes
, try_parse
, and write_str
.deframe
to allow consuming bytes without returning a framewrite_bytes
to write as many bytes as it can,
and return new NoWritableSpace
error only when it cannot write any bytes.
Remove NotEnoughSpaceError
. The method now behaves like std::io::Write::write
.From<NotEnoughSpaceError>
and From<MalformedInputError>
for String
.FixedBuf<1024>
.new
arg.capacity
.Copy
impl.writable
return type to &mut [u8]
.read_byte
,
try_read_byte
,
try_read_bytes
,
try_read_exact
,
try_parse
.UnwindSafe
deframe
and
mem
,
needed by AsyncFixedBuf::read_frame
.fixed_buffer_tokio
.copy_once_from
,
read_block
,
ReadWriteChain
,
and
ReadWriteTake
.FixedBuf::escape_ascii
.filled
constructor.read_delimited
to return Option<&[u8]>
, for clean EOF handling.clear()
.FixedBuf<[u8; 42]>
.AsRef<[u8]> + AsMut<[u8]>
value for internal memory:
[u8; N]
Box<[u8; N]>
&mut [u8]
Vec<u8>
new_with_mem
to new
.
Use FixedBuf::default()
to construct any FixedBuf<T: Default>
, which includes
arrays of sizes up to 32.docs.rs
.buf.slice(buf.read_frame(&mut reader, deframe_crlf))
frame_copy_iter
function.
Because of borrowing rules, this function must return non-borrowed (allocated and copied) data.Cargo.toml
and bump version number.../release.sh
License: Apache-2.0