From c734a627a88f48f4c3d629609d383d66e3ae190a Mon Sep 17 00:00:00 2001 From: Dominik Csapak Date: Fri, 3 Jul 2020 11:56:41 +0200 Subject: [PATCH] tools/byte_buffer: add examples and docs Signed-off-by: Dominik Csapak --- proxmox/src/tools/byte_buffer.rs | 73 +++++++++++++++++++++++++++++++- 1 file changed, 72 insertions(+), 1 deletion(-) diff --git a/proxmox/src/tools/byte_buffer.rs b/proxmox/src/tools/byte_buffer.rs index 8ca449bd..8ffee6f0 100644 --- a/proxmox/src/tools/byte_buffer.rs +++ b/proxmox/src/tools/byte_buffer.rs @@ -6,7 +6,6 @@ //! ``` //! # use std::io::Read; //! # use proxmox::tools::byte_buffer::ByteBuffer; -//! //! fn code(input: &mut T) -> std::io::Result> { //! let mut buffer = ByteBuffer::new(); //! let amount = buffer.read_from(input)?; @@ -23,6 +22,10 @@ use crate::tools::vec; 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 { buf: Box<[u8]>, data_size: usize, @@ -30,6 +33,8 @@ pub struct ByteBuffer { } impl ByteBuffer { + + /// Creates a new instance with a default capacity of 4096 pub fn new() -> Self { 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 { self.data_size } @@ -58,6 +64,25 @@ impl ByteBuffer { 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) { if self.data_size + size > self.capacity { panic!("size bigger than capacity!"); @@ -65,14 +90,45 @@ impl ByteBuffer { 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] { &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] { &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]> { let size = min(max_amount, self.data_size); let mut tmp = Vec::with_capacity(size); @@ -82,12 +138,27 @@ impl ByteBuffer { 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(&mut self, input: &mut T) -> Result { let amount = input.read(self.get_free_mut_slice())?; self.add_size(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(&mut self, input: &mut T) -> Result { let amount = input.read(self.get_free_mut_slice()).await?; self.add_size(amount);