mirror of
https://git.proxmox.com/git/proxmox
synced 2025-05-30 21:51:38 +00:00
tools/byte_buffer: add examples and docs
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
This commit is contained in:
parent
6fffca783e
commit
c734a627a8
@ -6,7 +6,6 @@
|
|||||||
//! ```
|
//! ```
|
||||||
//! # use std::io::Read;
|
//! # use std::io::Read;
|
||||||
//! # use proxmox::tools::byte_buffer::ByteBuffer;
|
//! # use proxmox::tools::byte_buffer::ByteBuffer;
|
||||||
//!
|
|
||||||
//! fn code<T: Read>(input: &mut T) -> std::io::Result<Box<[u8]>> {
|
//! fn code<T: Read>(input: &mut T) -> std::io::Result<Box<[u8]>> {
|
||||||
//! let mut buffer = ByteBuffer::new();
|
//! let mut buffer = ByteBuffer::new();
|
||||||
//! let amount = buffer.read_from(input)?;
|
//! let amount = buffer.read_from(input)?;
|
||||||
@ -23,6 +22,10 @@ use crate::tools::vec;
|
|||||||
|
|
||||||
use tokio::io::AsyncReadExt;
|
use tokio::io::AsyncReadExt;
|
||||||
|
|
||||||
|
/// A Buffer that holds bytes (u8)
|
||||||
|
/// has convenience methods for reading (with any reader that
|
||||||
|
/// implements std::io::Read or tokio::io::AsyncRead) onto the back
|
||||||
|
/// and consuming from the front
|
||||||
pub struct ByteBuffer {
|
pub struct ByteBuffer {
|
||||||
buf: Box<[u8]>,
|
buf: Box<[u8]>,
|
||||||
data_size: usize,
|
data_size: usize,
|
||||||
@ -30,6 +33,8 @@ pub struct ByteBuffer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ByteBuffer {
|
impl ByteBuffer {
|
||||||
|
|
||||||
|
/// Creates a new instance with a default capacity of 4096
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self::with_capacity(4096)
|
Self::with_capacity(4096)
|
||||||
}
|
}
|
||||||
@ -42,6 +47,7 @@ impl ByteBuffer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the length of the data in the Buffer
|
||||||
pub fn data_size(&self) -> usize {
|
pub fn data_size(&self) -> usize {
|
||||||
self.data_size
|
self.data_size
|
||||||
}
|
}
|
||||||
@ -58,6 +64,25 @@ impl ByteBuffer {
|
|||||||
self.data_size >= self.capacity
|
self.data_size >= self.capacity
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets the length of the data. Useful if data was manually added
|
||||||
|
/// with a mutable slice (e.g. from [get_free_mut_slice](#method.get_free_mut_slice)).
|
||||||
|
///
|
||||||
|
/// Panics when new size would be greater than capacity.
|
||||||
|
///
|
||||||
|
/// Example:
|
||||||
|
/// ```
|
||||||
|
/// # use proxmox::tools::byte_buffer::ByteBuffer;
|
||||||
|
/// let mut buf = ByteBuffer::new();
|
||||||
|
/// buf.get_free_mut_slice()[..1].copy_from_slice(&[1u8]);
|
||||||
|
/// buf.add_size(1);
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// This code will panic:
|
||||||
|
/// ```should_panic
|
||||||
|
/// # use proxmox::tools::byte_buffer::ByteBuffer;
|
||||||
|
/// let mut buf = ByteBuffer::with_capacity(128);
|
||||||
|
/// buf.add_size(256);
|
||||||
|
/// ```
|
||||||
pub fn add_size(&mut self, size: usize) {
|
pub fn add_size(&mut self, size: usize) {
|
||||||
if self.data_size + size > self.capacity {
|
if self.data_size + size > self.capacity {
|
||||||
panic!("size bigger than capacity!");
|
panic!("size bigger than capacity!");
|
||||||
@ -65,14 +90,45 @@ impl ByteBuffer {
|
|||||||
self.data_size += size;
|
self.data_size += size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Gets an immutable reference to the data in the buffer
|
||||||
|
/// Example:
|
||||||
|
/// ```
|
||||||
|
/// # use proxmox::tools::byte_buffer::ByteBuffer;
|
||||||
|
/// let mut buf = ByteBuffer::new();
|
||||||
|
/// buf.get_free_mut_slice()[..2].copy_from_slice(&[1u8, 2u8]);
|
||||||
|
/// buf.add_size(2);
|
||||||
|
/// assert_eq!(buf.get_data_slice(), &[1u8, 2u8]);
|
||||||
|
/// ```
|
||||||
pub fn get_data_slice(&self) -> &[u8] {
|
pub fn get_data_slice(&self) -> &[u8] {
|
||||||
&self.buf[..self.data_size]
|
&self.buf[..self.data_size]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a mutable reference to the free section of the
|
||||||
|
/// Buffer. There are no guarantees about the content of the
|
||||||
|
/// free part of the Buffer (may even be uninitialized).
|
||||||
|
/// see [add_size](#method.add_size) for a usage example.
|
||||||
pub fn get_free_mut_slice(&mut self) -> &mut [u8] {
|
pub fn get_free_mut_slice(&mut self) -> &mut [u8] {
|
||||||
&mut self.buf[self.data_size..self.capacity]
|
&mut self.buf[self.data_size..self.capacity]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Consumes up to max_amount of data from the front
|
||||||
|
/// of the buffer. If there was less than max_amount present,
|
||||||
|
/// it will return as much data as there was in the buffer.
|
||||||
|
/// The rest of the data will be moved to the front, and
|
||||||
|
/// the data size will be updated accordingly.
|
||||||
|
///
|
||||||
|
/// Example:
|
||||||
|
/// ```
|
||||||
|
/// # use proxmox::tools::byte_buffer::ByteBuffer;
|
||||||
|
/// let mut buf = ByteBuffer::new();
|
||||||
|
/// buf.get_free_mut_slice()[..2].copy_from_slice(&[1u8, 2u8]);
|
||||||
|
/// buf.add_size(2);
|
||||||
|
/// assert_eq!(buf.data_size(), 2);
|
||||||
|
///
|
||||||
|
/// let data = buf.consume(100);
|
||||||
|
/// assert_eq!(data, vec![1u8, 2u8].into_boxed_slice());
|
||||||
|
/// assert!(buf.is_empty());
|
||||||
|
/// ```
|
||||||
pub fn consume(&mut self, max_amount: usize) -> Box<[u8]> {
|
pub fn consume(&mut self, max_amount: usize) -> Box<[u8]> {
|
||||||
let size = min(max_amount, self.data_size);
|
let size = min(max_amount, self.data_size);
|
||||||
let mut tmp = Vec::with_capacity(size);
|
let mut tmp = Vec::with_capacity(size);
|
||||||
@ -82,12 +138,27 @@ impl ByteBuffer {
|
|||||||
tmp.into_boxed_slice()
|
tmp.into_boxed_slice()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Takes a reader and reads into the back of the buffer (up to the
|
||||||
|
/// free space in the buffer) and updates its size accordingly.
|
||||||
|
///
|
||||||
|
/// Example:
|
||||||
|
/// ```norun
|
||||||
|
/// // create some reader
|
||||||
|
/// let reader = ...;
|
||||||
|
///
|
||||||
|
/// let mut buf = ByteBuffer::new();
|
||||||
|
/// let res = buf.read_from(reader);
|
||||||
|
/// // do something with the buffer
|
||||||
|
/// ...
|
||||||
|
/// ```
|
||||||
pub fn read_from<T: Read>(&mut self, input: &mut T) -> Result<usize> {
|
pub fn read_from<T: Read>(&mut self, input: &mut T) -> Result<usize> {
|
||||||
let amount = input.read(self.get_free_mut_slice())?;
|
let amount = input.read(self.get_free_mut_slice())?;
|
||||||
self.add_size(amount);
|
self.add_size(amount);
|
||||||
Ok(amount)
|
Ok(amount)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Same as read_from, but for reader that implement tokio::io::AsyncRead.
|
||||||
|
/// See [read_from](#method.read_from) for an example
|
||||||
pub async fn read_from_async<T: AsyncReadExt + Unpin>(&mut self, input: &mut T) -> Result<usize> {
|
pub async fn read_from_async<T: AsyncReadExt + Unpin>(&mut self, input: &mut T) -> Result<usize> {
|
||||||
let amount = input.read(self.get_free_mut_slice()).await?;
|
let amount = input.read(self.get_free_mut_slice()).await?;
|
||||||
self.add_size(amount);
|
self.add_size(amount);
|
||||||
|
Loading…
Reference in New Issue
Block a user