From: Dominik Csapak <d.csapak@proxmox.com>
To: pbs-devel@lists.proxmox.com
Subject: [pbs-devel] [PATCH proxmox 1/9] proxmox/tools/byte_buffer: improve ByteBuffer interface
Date: Tue, 14 Jul 2020 13:09:49 +0200 [thread overview]
Message-ID: <20200714110957.31884-2-d.csapak@proxmox.com> (raw)
In-Reply-To: <20200714110957.31884-1-d.csapak@proxmox.com>
by implementing Deref and DerefMut, renaming consume to 'remove_data'
adapt the usage inside of websocket (we did not use it anywhere else for now)
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
proxmox/src/tools/byte_buffer.rs | 91 ++++++++++++++++++++------------
proxmox/src/tools/websocket.rs | 11 ++--
2 files changed, 64 insertions(+), 38 deletions(-)
diff --git a/proxmox/src/tools/byte_buffer.rs b/proxmox/src/tools/byte_buffer.rs
index abfa6c8..7d4fce4 100644
--- a/proxmox/src/tools/byte_buffer.rs
+++ b/proxmox/src/tools/byte_buffer.rs
@@ -9,14 +9,13 @@
//! fn code<T: Read + ?Sized>(input: &mut T) -> std::io::Result<Box<[u8]>> {
//! let mut buffer = ByteBuffer::new();
//! let amount = buffer.read_from(input)?;
-//! let data = buffer.consume(amount);
+//! let data = buffer.remove_data(amount);
//! assert_eq!(data.len(), amount);
//! Ok(data)
//! }
//! # code(&mut &b"testdata"[..]).expect("byte buffer test failed");
//! ```
-use std::cmp::min;
use std::io::{Read, Result};
use crate::tools::vec;
@@ -49,23 +48,18 @@ impl ByteBuffer {
}
}
- /// Returns the length of the data in the Buffer
- pub fn data_size(&self) -> usize {
- self.data_size
- }
-
pub fn free_size(&self) -> usize {
self.capacity - self.data_size
}
- pub fn is_empty(&self) -> bool {
- self.data_size == 0
- }
-
pub fn is_full(&self) -> bool {
self.data_size >= self.capacity
}
+ pub fn clear(&mut self) {
+ self.data_size = 0
+ }
+
/// 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)).
///
@@ -92,19 +86,6 @@ 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).
@@ -113,8 +94,8 @@ impl ByteBuffer {
&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,
+ /// Removes up to max_amount of data from the front
+ /// of the buffer and returns. 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.
@@ -125,20 +106,50 @@ impl 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);
+ /// assert_eq!(buf.len(), 2);
///
- /// let data = buf.consume(100);
+ /// let data = buf.remove_data(100);
/// assert_eq!(&data[..], &[1u8, 2u8]);
/// assert!(buf.is_empty());
/// ```
- pub fn consume(&mut self, max_amount: usize) -> Box<[u8]> {
- let size = min(max_amount, self.data_size);
+ #[must_use]
+ pub fn remove_data(&mut self, max_amount: usize) -> Box<[u8]> {
+ let size = max_amount.min(self.data_size);
let tmp: Box<[u8]> = self.buf[..size].into();
self.buf.copy_within(size..self.capacity, 0);
self.data_size -= size;
tmp
}
+ /// Removes up to max_amount of data from the front and returns
+ /// the amount of data removed. If there was less than max_amount present,
+ /// it will empty out the buffer and return the amount removed.
+ ///
+ /// 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.len(), 2);
+ ///
+ /// let amount = buf.consume(1);
+ /// assert_eq!(amount, 1);
+ /// let amount = buf.consume(100);
+ /// assert_eq!(amount, 1);
+ /// assert!(buf.is_empty());
+ /// ```
+ pub fn consume(&mut self, max_amount: usize) -> usize {
+ let size = max_amount.min(self.data_size);
+ if size < max_amount {
+ self.clear()
+ } else {
+ self.buf.copy_within(size..self.capacity, 0);
+ self.data_size -= size;
+ }
+ size
+ }
+
/// Takes a reader and reads into the back of the buffer (up to the
/// free space in the buffer) and updates its size accordingly.
///
@@ -168,6 +179,20 @@ impl ByteBuffer {
}
}
+impl std::ops::Deref for ByteBuffer {
+ type Target = [u8];
+
+ fn deref(&self) -> &Self::Target {
+ &self.buf[..self.data_size]
+ }
+}
+
+impl std::ops::DerefMut for ByteBuffer {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ &mut self.buf[..self.data_size]
+ }
+}
+
#[cfg(test)]
mod test {
use crate::tools::byte_buffer::ByteBuffer;
@@ -181,7 +206,7 @@ mod test {
}
buffer.add_size(5);
- let slice2 = buffer.get_data_slice();
+ let slice2 = &buffer[..];
assert_eq!(slice2, &[0, 1, 2, 3, 4]);
}
@@ -190,7 +215,7 @@ mod test {
fn test2() {
let mut buffer = ByteBuffer::with_capacity(1024);
let size = buffer.read_from(&mut std::io::repeat(54)).unwrap();
- assert_eq!(buffer.data_size(), size);
- assert_eq!(buffer.get_data_slice()[0], 54);
+ assert_eq!(buffer.len(), size);
+ assert_eq!(buffer[0], 54);
}
}
diff --git a/proxmox/src/tools/websocket.rs b/proxmox/src/tools/websocket.rs
index 3877e4e..04173bb 100644
--- a/proxmox/src/tools/websocket.rs
+++ b/proxmox/src/tools/websocket.rs
@@ -485,7 +485,7 @@ impl<R: AsyncReadExt + Unpin + Send + 'static> AsyncRead for WebSocketReader<R>
let mut header = match this.header.take() {
Some(header) => header,
None => {
- let header = match FrameHeader::try_from_bytes(read_buffer.get_data_slice())? {
+ let header = match FrameHeader::try_from_bytes(&read_buffer[..])? {
Ok(header) => header,
Err(_) => {
this.state = ReaderState::NoData;
@@ -500,12 +500,12 @@ impl<R: AsyncReadExt + Unpin + Send + 'static> AsyncRead for WebSocketReader<R>
};
if header.is_control_frame() {
- if read_buffer.data_size() >= header.payload_len {
+ if read_buffer.len() >= header.payload_len {
(this.callback)(
header.frametype,
mask_bytes(
header.mask,
- &mut read_buffer.consume(header.payload_len).into_vec(),
+ &mut read_buffer.remove_data(header.payload_len).into_vec(),
),
);
this.state = if read_buffer.is_empty() {
@@ -523,8 +523,9 @@ impl<R: AsyncReadExt + Unpin + Send + 'static> AsyncRead for WebSocketReader<R>
}
}
- let len = min(buf.len() - offset, min(header.payload_len, read_buffer.data_size()));
- let mut data = read_buffer.consume(len).into_vec();
+ let len = min(buf.len() - offset, min(header.payload_len, read_buffer.len()));
+
+ let mut data = read_buffer.remove_data(len).into_vec();
buf[offset..offset+len].copy_from_slice(mask_bytes(header.mask, &mut data));
offset += len;
--
2.20.1
next prev parent reply other threads:[~2020-07-14 11:10 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-07-14 11:09 [pbs-devel] [PATCH proxmox 0/9] preparation for websocket api Dominik Csapak
2020-07-14 11:09 ` Dominik Csapak [this message]
2020-07-14 11:09 ` [pbs-devel] [PATCH proxmox 2/9] proxmox/tools/byte_buffer: impl Default Dominik Csapak
2020-07-14 11:09 ` [pbs-devel] [PATCH proxmox 3/9] proxmox/tools/websocket: use ready macro for WebSocketWriter Dominik Csapak
2020-07-14 11:09 ` [pbs-devel] [PATCH proxmox 4/9] proxmox/tools/websocket: correctly return eof Dominik Csapak
2020-07-14 11:09 ` [pbs-devel] [PATCH proxmox 5/9] proxmox/tools/websocket: use io::Error and Result explicitely Dominik Csapak
2020-07-14 11:09 ` [pbs-devel] [PATCH proxmox 6/9] proxmox/tools/websocket: improve mask_bytes and create_frame interface Dominik Csapak
2020-07-15 9:08 ` [pbs-devel] [PATCH proxmox v2 " Dominik Csapak
2020-07-14 11:09 ` [pbs-devel] [PATCH proxmox 7/9] proxmox/tools/websocket: implement send_control_frame for writer Dominik Csapak
2020-07-14 11:09 ` [pbs-devel] [PATCH proxmox 8/9] proxmox/tools/websocket: replace CallBack with a channel Dominik Csapak
2020-07-14 11:09 ` [pbs-devel] [PATCH proxmox 9/9] proxmox/tools/websocket: add WebSocket implementation Dominik Csapak
2020-07-15 8:15 ` [pbs-devel] [PATCH proxmox 0/9] preparation for websocket api Fabian Grünbichler
2020-07-15 8:31 ` Dominik Csapak
2020-07-15 13:00 ` [pbs-devel] applied: " Wolfgang Bumiller
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200714110957.31884-2-d.csapak@proxmox.com \
--to=d.csapak@proxmox.com \
--cc=pbs-devel@lists.proxmox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox