forked from lx/netapp
167 lines
3.9 KiB
Rust
167 lines
3.9 KiB
Rust
use std::collections::VecDeque;
|
|
|
|
pub use bytes::Bytes;
|
|
|
|
/// A circular buffer of bytes, internally represented as a list of Bytes
|
|
/// for optimization, but that for all intent and purposes acts just like
|
|
/// a big byte slice which can be extended on the right and from which
|
|
/// one can take on the left.
|
|
pub struct BytesBuf {
|
|
buf: VecDeque<Bytes>,
|
|
buf_len: usize,
|
|
}
|
|
|
|
impl BytesBuf {
|
|
/// Creates a new empty BytesBuf
|
|
pub fn new() -> Self {
|
|
Self {
|
|
buf: VecDeque::new(),
|
|
buf_len: 0,
|
|
}
|
|
}
|
|
|
|
/// Returns the number of bytes stored in the BytesBuf
|
|
#[inline]
|
|
pub fn len(&self) -> usize {
|
|
self.buf_len
|
|
}
|
|
|
|
/// Returns true iff the BytesBuf contains zero bytes
|
|
#[inline]
|
|
pub fn is_empty(&self) -> bool {
|
|
self.buf_len == 0
|
|
}
|
|
|
|
/// Adds some bytes to the right of the buffer
|
|
pub fn extend(&mut self, b: Bytes) {
|
|
if !b.is_empty() {
|
|
self.buf_len += b.len();
|
|
self.buf.push_back(b);
|
|
}
|
|
}
|
|
|
|
/// Takes the whole content of the buffer and returns it as a single Bytes unit
|
|
pub fn take_all(&mut self) -> Bytes {
|
|
if self.buf.len() == 0 {
|
|
Bytes::new()
|
|
} else if self.buf.len() == 1 {
|
|
self.buf_len = 0;
|
|
self.buf.pop_back().unwrap()
|
|
} else {
|
|
let mut ret = Vec::with_capacity(self.buf_len);
|
|
for b in self.buf.iter() {
|
|
ret.extend(&b[..]);
|
|
}
|
|
self.buf.clear();
|
|
self.buf_len = 0;
|
|
Bytes::from(ret)
|
|
}
|
|
}
|
|
|
|
/// Takes at most max_len bytes from the left of the buffer
|
|
pub fn take_max(&mut self, max_len: usize) -> Bytes {
|
|
if self.buf_len <= max_len {
|
|
self.take_all()
|
|
} else {
|
|
self.take_exact_ok(max_len)
|
|
}
|
|
}
|
|
|
|
/// Take exactly len bytes from the left of the buffer, returns None if
|
|
/// the BytesBuf doesn't contain enough data
|
|
pub fn take_exact(&mut self, len: usize) -> Option<Bytes> {
|
|
if self.buf_len < len {
|
|
None
|
|
} else {
|
|
Some(self.take_exact_ok(len))
|
|
}
|
|
}
|
|
|
|
fn take_exact_ok(&mut self, len: usize) -> Bytes {
|
|
assert!(len <= self.buf_len);
|
|
let front = self.buf.pop_front().unwrap();
|
|
if front.len() > len {
|
|
self.buf.push_front(front.slice(len..));
|
|
self.buf_len -= len;
|
|
front.slice(..len)
|
|
} else if front.len() == len {
|
|
self.buf_len -= len;
|
|
front
|
|
} else {
|
|
let mut ret = Vec::with_capacity(len);
|
|
ret.extend(&front[..]);
|
|
self.buf_len -= front.len();
|
|
while ret.len() < len {
|
|
let front = self.buf.pop_front().unwrap();
|
|
if front.len() > len - ret.len() {
|
|
let take = len - ret.len();
|
|
ret.extend(front.slice(..take));
|
|
self.buf.push_front(front.slice(take..));
|
|
self.buf_len -= take;
|
|
break;
|
|
} else {
|
|
ret.extend(&front[..]);
|
|
self.buf_len -= front.len();
|
|
}
|
|
}
|
|
Bytes::from(ret)
|
|
}
|
|
}
|
|
|
|
/// Return the internal sequence of Bytes slices that make up the buffer
|
|
pub fn into_slices(self) -> VecDeque<Bytes> {
|
|
self.buf
|
|
}
|
|
}
|
|
|
|
impl From<Bytes> for BytesBuf {
|
|
fn from(b: Bytes) -> BytesBuf {
|
|
let mut ret = BytesBuf::new();
|
|
ret.extend(b);
|
|
ret
|
|
}
|
|
}
|
|
|
|
impl From<BytesBuf> for Bytes {
|
|
fn from(mut b: BytesBuf) -> Bytes {
|
|
b.take_all()
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod test {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_bytes_buf() {
|
|
let mut buf = BytesBuf::new();
|
|
assert!(buf.len() == 0);
|
|
assert!(buf.is_empty());
|
|
|
|
buf.extend(Bytes::from(b"Hello, world!".to_vec()));
|
|
assert!(buf.len() == 13);
|
|
assert!(!buf.is_empty());
|
|
|
|
buf.extend(Bytes::from(b"1234567890".to_vec()));
|
|
assert!(buf.len() == 23);
|
|
assert!(!buf.is_empty());
|
|
|
|
assert_eq!(buf.take_all(), Bytes::from(b"Hello, world!1234567890".to_vec()));
|
|
assert!(buf.len() == 0);
|
|
assert!(buf.is_empty());
|
|
|
|
buf.extend(Bytes::from(b"1234567890".to_vec()));
|
|
buf.extend(Bytes::from(b"Hello, world!".to_vec()));
|
|
assert!(buf.len() == 23);
|
|
assert!(!buf.is_empty());
|
|
|
|
assert_eq!(buf.take_max(12), Bytes::from(b"1234567890He".to_vec()));
|
|
assert!(buf.len() == 11);
|
|
|
|
assert_eq!(buf.take_exact(12), None);
|
|
assert!(buf.len() == 11);
|
|
assert_eq!(buf.take_exact(11), Some(Bytes::from(b"llo, world!".to_vec())));
|
|
assert!(buf.len() == 0);
|
|
assert!(buf.is_empty());
|
|
}
|
|
}
|