implement BufMut for Buffer
This commit is contained in:
parent
8d9566dbb8
commit
0a9c9ab1e2
|
@ -17,3 +17,4 @@ include = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
bytes = "1.8.0"
|
||||||
|
|
674
src/lib.rs
674
src/lib.rs
|
@ -47,369 +47,421 @@
|
||||||
//! assert_eq!(b.data(), &b"cd"[..]);
|
//! assert_eq!(b.data(), &b"cd"[..]);
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
use std::{cmp, ptr};
|
use std::io::{self, Read, Write};
|
||||||
use std::io::{self,Write,Read};
|
|
||||||
use std::iter::repeat;
|
use std::iter::repeat;
|
||||||
|
use std::{cmp, ptr};
|
||||||
|
|
||||||
|
extern crate bytes;
|
||||||
|
use bytes::BufMut;
|
||||||
|
|
||||||
/// the Buffer contains the underlying memory and data positions
|
/// the Buffer contains the underlying memory and data positions
|
||||||
///
|
///
|
||||||
/// In all cases, `0 ≤ position ≤ end ≤ capacity` should be true
|
/// In all cases, `0 ≤ position ≤ end ≤ capacity` should be true
|
||||||
#[derive(Debug,PartialEq,Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub struct Buffer {
|
pub struct Buffer {
|
||||||
/// the Vec containing the data
|
/// the Vec containing the data
|
||||||
memory: Vec<u8>,
|
memory: Vec<u8>,
|
||||||
/// the current capacity of the Buffer
|
/// the current capacity of the Buffer
|
||||||
capacity: usize,
|
capacity: usize,
|
||||||
/// the current beginning of the available data
|
/// the current beginning of the available data
|
||||||
position: usize,
|
position: usize,
|
||||||
/// the current end of the available data
|
/// the current end of the available data
|
||||||
/// and beginning of the available space
|
/// and beginning of the available space
|
||||||
end: usize
|
end: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Buffer {
|
impl Buffer {
|
||||||
/// allocates a new buffer of maximum size `capacity`
|
/// allocates a new buffer of maximum size `capacity`
|
||||||
pub fn with_capacity(capacity: usize) -> Buffer {
|
pub fn with_capacity(capacity: usize) -> Buffer {
|
||||||
let mut v = Vec::with_capacity(capacity);
|
let mut v = Vec::with_capacity(capacity);
|
||||||
v.extend(repeat(0).take(capacity));
|
v.extend(repeat(0).take(capacity));
|
||||||
Buffer {
|
Buffer {
|
||||||
memory: v,
|
memory: v,
|
||||||
capacity: capacity,
|
capacity: capacity,
|
||||||
position: 0,
|
position: 0,
|
||||||
end: 0
|
end: 0,
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// allocates a new buffer containing the slice `data`
|
|
||||||
///
|
|
||||||
/// the buffer starts full, its available data size is exactly `data.len()`
|
|
||||||
pub fn from_slice(data: &[u8]) -> Buffer {
|
|
||||||
Buffer {
|
|
||||||
memory: Vec::from(data),
|
|
||||||
capacity: data.len(),
|
|
||||||
position: 0,
|
|
||||||
end: data.len()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// increases the size of the buffer
|
|
||||||
///
|
|
||||||
/// this does nothing if the buffer is already large enough
|
|
||||||
pub fn grow(&mut self, new_size: usize) -> bool {
|
|
||||||
if self.capacity >= new_size {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.memory.resize(new_size, 0);
|
/// allocates a new buffer containing the slice `data`
|
||||||
self.capacity = new_size;
|
///
|
||||||
true
|
/// the buffer starts full, its available data size is exactly `data.len()`
|
||||||
}
|
pub fn from_slice(data: &[u8]) -> Buffer {
|
||||||
|
Buffer {
|
||||||
/// returns how much data can be read from the buffer
|
memory: Vec::from(data),
|
||||||
pub fn available_data(&self) -> usize {
|
capacity: data.len(),
|
||||||
self.end - self.position
|
position: 0,
|
||||||
}
|
end: data.len(),
|
||||||
|
}
|
||||||
/// returns how much free space is available to write to
|
|
||||||
pub fn available_space(&self) -> usize {
|
|
||||||
self.capacity - self.end
|
|
||||||
}
|
|
||||||
|
|
||||||
/// returns the underlying vector's size
|
|
||||||
pub fn capacity(&self) -> usize {
|
|
||||||
self.capacity
|
|
||||||
}
|
|
||||||
|
|
||||||
/// returns true if there is no more data to read
|
|
||||||
pub fn empty(&self) -> bool {
|
|
||||||
self.position == self.end
|
|
||||||
}
|
|
||||||
|
|
||||||
/// advances the position tracker
|
|
||||||
///
|
|
||||||
/// if the position gets past the buffer's half,
|
|
||||||
/// this will call `shift()` to move the remaining data
|
|
||||||
/// to the beginning of the buffer
|
|
||||||
pub fn consume(&mut self, count: usize) -> usize {
|
|
||||||
let cnt = cmp::min(count, self.available_data());
|
|
||||||
self.position += cnt;
|
|
||||||
if self.position > self.capacity / 2 {
|
|
||||||
//trace!("consume shift: pos {}, end {}", self.position, self.end);
|
|
||||||
self.shift();
|
|
||||||
}
|
|
||||||
cnt
|
|
||||||
}
|
|
||||||
|
|
||||||
/// advances the position tracker
|
|
||||||
///
|
|
||||||
/// This method is similar to `consume()` but will not move data
|
|
||||||
/// to the beginning of the buffer
|
|
||||||
pub fn consume_noshift(&mut self, count: usize) -> usize {
|
|
||||||
let cnt = cmp::min(count, self.available_data());
|
|
||||||
self.position += cnt;
|
|
||||||
cnt
|
|
||||||
}
|
|
||||||
|
|
||||||
/// after having written data to the buffer, use this function
|
|
||||||
/// to indicate how many bytes were written
|
|
||||||
///
|
|
||||||
/// if there is not enough available space, this function can call
|
|
||||||
/// `shift()` to move the remaining data to the beginning of the
|
|
||||||
/// buffer
|
|
||||||
pub fn fill(&mut self, count: usize) -> usize {
|
|
||||||
let cnt = cmp::min(count, self.available_space());
|
|
||||||
self.end += cnt;
|
|
||||||
if self.available_space() < self.available_data() + cnt {
|
|
||||||
//trace!("fill shift: pos {}, end {}", self.position, self.end);
|
|
||||||
self.shift();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cnt
|
/// increases the size of the buffer
|
||||||
}
|
///
|
||||||
|
/// this does nothing if the buffer is already large enough
|
||||||
|
pub fn grow(&mut self, new_size: usize) -> bool {
|
||||||
|
if self.capacity >= new_size {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/// Get the current position
|
self.memory.resize(new_size, 0);
|
||||||
///
|
self.capacity = new_size;
|
||||||
/// # Examples
|
true
|
||||||
/// ```
|
}
|
||||||
/// use circular::Buffer;
|
|
||||||
/// use std::io::{Read,Write};
|
|
||||||
///
|
|
||||||
/// let mut output = [0;5];
|
|
||||||
///
|
|
||||||
/// let mut b = Buffer::with_capacity(10);
|
|
||||||
///
|
|
||||||
/// let res = b.write(&b"abcdefgh"[..]);
|
|
||||||
///
|
|
||||||
/// b.read(&mut output);
|
|
||||||
///
|
|
||||||
/// // Position must be 5
|
|
||||||
/// assert_eq!(b.position(), 5);
|
|
||||||
/// assert_eq!(b.available_data(), 3);
|
|
||||||
/// ```
|
|
||||||
pub fn position(&self) -> usize {
|
|
||||||
self.position
|
|
||||||
}
|
|
||||||
|
|
||||||
/// moves the position and end trackers to the beginning
|
/// returns how much data can be read from the buffer
|
||||||
/// this function does not modify the data
|
pub fn available_data(&self) -> usize {
|
||||||
pub fn reset(&mut self) {
|
self.end - self.position
|
||||||
self.position = 0;
|
}
|
||||||
self.end = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// returns a slice with all the available data
|
/// returns how much free space is available to write to
|
||||||
pub fn data(&self) -> &[u8] {
|
pub fn available_space(&self) -> usize {
|
||||||
&self.memory[self.position..self.end]
|
self.capacity - self.end
|
||||||
}
|
}
|
||||||
|
|
||||||
/// returns a mutable slice with all the available space to
|
/// returns the underlying vector's size
|
||||||
/// write to
|
pub fn capacity(&self) -> usize {
|
||||||
pub fn space(&mut self) -> &mut[u8] {
|
self.capacity
|
||||||
&mut self.memory[self.end..self.capacity]
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// moves the data at the beginning of the buffer
|
/// returns true if there is no more data to read
|
||||||
///
|
pub fn empty(&self) -> bool {
|
||||||
/// if the position was more than 0, it is now 0
|
self.position == self.end
|
||||||
pub fn shift(&mut self) {
|
}
|
||||||
if self.position > 0 {
|
|
||||||
unsafe {
|
/// advances the position tracker
|
||||||
let length = self.end - self.position;
|
///
|
||||||
ptr::copy( (&self.memory[self.position..self.end]).as_ptr(), (&mut self.memory[..length]).as_mut_ptr(), length);
|
/// if the position gets past the buffer's half,
|
||||||
|
/// this will call `shift()` to move the remaining data
|
||||||
|
/// to the beginning of the buffer
|
||||||
|
pub fn consume(&mut self, count: usize) -> usize {
|
||||||
|
let cnt = cmp::min(count, self.available_data());
|
||||||
|
self.position += cnt;
|
||||||
|
if self.position > self.capacity / 2 {
|
||||||
|
//trace!("consume shift: pos {}, end {}", self.position, self.end);
|
||||||
|
self.shift();
|
||||||
|
}
|
||||||
|
cnt
|
||||||
|
}
|
||||||
|
|
||||||
|
/// advances the position tracker
|
||||||
|
///
|
||||||
|
/// This method is similar to `consume()` but will not move data
|
||||||
|
/// to the beginning of the buffer
|
||||||
|
pub fn consume_noshift(&mut self, count: usize) -> usize {
|
||||||
|
let cnt = cmp::min(count, self.available_data());
|
||||||
|
self.position += cnt;
|
||||||
|
cnt
|
||||||
|
}
|
||||||
|
|
||||||
|
/// after having written data to the buffer, use this function
|
||||||
|
/// to indicate how many bytes were written
|
||||||
|
///
|
||||||
|
/// if there is not enough available space, this function can call
|
||||||
|
/// `shift()` to move the remaining data to the beginning of the
|
||||||
|
/// buffer
|
||||||
|
pub fn fill(&mut self, count: usize) -> usize {
|
||||||
|
let cnt = cmp::min(count, self.available_space());
|
||||||
|
self.end += cnt;
|
||||||
|
if self.available_space() < self.available_data() + cnt {
|
||||||
|
//trace!("fill shift: pos {}, end {}", self.position, self.end);
|
||||||
|
self.shift();
|
||||||
|
}
|
||||||
|
|
||||||
|
cnt
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the current position
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
/// ```
|
||||||
|
/// use circular::Buffer;
|
||||||
|
/// use std::io::{Read,Write};
|
||||||
|
///
|
||||||
|
/// let mut output = [0;5];
|
||||||
|
///
|
||||||
|
/// let mut b = Buffer::with_capacity(10);
|
||||||
|
///
|
||||||
|
/// let res = b.write(&b"abcdefgh"[..]);
|
||||||
|
///
|
||||||
|
/// b.read(&mut output);
|
||||||
|
///
|
||||||
|
/// // Position must be 5
|
||||||
|
/// assert_eq!(b.position(), 5);
|
||||||
|
/// assert_eq!(b.available_data(), 3);
|
||||||
|
/// ```
|
||||||
|
pub fn position(&self) -> usize {
|
||||||
|
self.position
|
||||||
|
}
|
||||||
|
|
||||||
|
/// moves the position and end trackers to the beginning
|
||||||
|
/// this function does not modify the data
|
||||||
|
pub fn reset(&mut self) {
|
||||||
self.position = 0;
|
self.position = 0;
|
||||||
self.end = length;
|
self.end = 0;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//FIXME: this should probably be rewritten, and tested extensively
|
|
||||||
#[doc(hidden)]
|
|
||||||
pub fn delete_slice(&mut self, start: usize, length: usize) -> Option<usize> {
|
|
||||||
if start + length >= self.available_data() {
|
|
||||||
return None
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe {
|
/// returns a slice with all the available data
|
||||||
let begin = self.position + start;
|
pub fn data(&self) -> &[u8] {
|
||||||
let next_end = self.end - length;
|
&self.memory[self.position..self.end]
|
||||||
ptr::copy(
|
|
||||||
(&self.memory[begin+length..self.end]).as_ptr(),
|
|
||||||
(&mut self.memory[begin..next_end]).as_mut_ptr(),
|
|
||||||
self.end - (begin+length)
|
|
||||||
);
|
|
||||||
self.end = next_end;
|
|
||||||
}
|
|
||||||
Some(self.available_data())
|
|
||||||
}
|
|
||||||
|
|
||||||
//FIXME: this should probably be rewritten, and tested extensively
|
|
||||||
#[doc(hidden)]
|
|
||||||
pub fn replace_slice(&mut self, data: &[u8], start: usize, length: usize) -> Option<usize> {
|
|
||||||
let data_len = data.len();
|
|
||||||
if start + length > self.available_data() ||
|
|
||||||
self.position + start + data_len > self.capacity {
|
|
||||||
return None
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe {
|
/// returns a mutable slice with all the available space to
|
||||||
let begin = self.position + start;
|
/// write to
|
||||||
let slice_end = begin + data_len;
|
pub fn space(&mut self) -> &mut [u8] {
|
||||||
// we reduced the data size
|
&mut self.memory[self.end..self.capacity]
|
||||||
if data_len < length {
|
|
||||||
ptr::copy(data.as_ptr(), (&mut self.memory[begin..slice_end]).as_mut_ptr(), data_len);
|
|
||||||
|
|
||||||
ptr::copy((&self.memory[start+length..self.end]).as_ptr(), (&mut self.memory[slice_end..]).as_mut_ptr(), self.end - (start + length));
|
|
||||||
self.end = self.end - (length - data_len);
|
|
||||||
|
|
||||||
// we put more data in the buffer
|
|
||||||
} else {
|
|
||||||
ptr::copy((&self.memory[start+length..self.end]).as_ptr(), (&mut self.memory[start+data_len..]).as_mut_ptr(), self.end - (start + length));
|
|
||||||
ptr::copy(data.as_ptr(), (&mut self.memory[begin..slice_end]).as_mut_ptr(), data_len);
|
|
||||||
self.end = self.end + data_len - length;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Some(self.available_data())
|
|
||||||
}
|
|
||||||
|
|
||||||
//FIXME: this should probably be rewritten, and tested extensively
|
|
||||||
#[doc(hidden)]
|
|
||||||
pub fn insert_slice(&mut self, data: &[u8], start: usize) -> Option<usize> {
|
|
||||||
let data_len = data.len();
|
|
||||||
if start > self.available_data() ||
|
|
||||||
self.position + self.end + data_len > self.capacity {
|
|
||||||
return None
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe {
|
/// moves the data at the beginning of the buffer
|
||||||
let begin = self.position + start;
|
///
|
||||||
let slice_end = begin + data_len;
|
/// if the position was more than 0, it is now 0
|
||||||
ptr::copy((&self.memory[start..self.end]).as_ptr(), (&mut self.memory[start+data_len..]).as_mut_ptr(), self.end - start);
|
pub fn shift(&mut self) {
|
||||||
ptr::copy(data.as_ptr(), (&mut self.memory[begin..slice_end]).as_mut_ptr(), data_len);
|
if self.position > 0 {
|
||||||
self.end = self.end + data_len;
|
unsafe {
|
||||||
|
let length = self.end - self.position;
|
||||||
|
ptr::copy(
|
||||||
|
(&self.memory[self.position..self.end]).as_ptr(),
|
||||||
|
(&mut self.memory[..length]).as_mut_ptr(),
|
||||||
|
length,
|
||||||
|
);
|
||||||
|
self.position = 0;
|
||||||
|
self.end = length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//FIXME: this should probably be rewritten, and tested extensively
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub fn delete_slice(&mut self, start: usize, length: usize) -> Option<usize> {
|
||||||
|
if start + length >= self.available_data() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let begin = self.position + start;
|
||||||
|
let next_end = self.end - length;
|
||||||
|
ptr::copy(
|
||||||
|
(&self.memory[begin + length..self.end]).as_ptr(),
|
||||||
|
(&mut self.memory[begin..next_end]).as_mut_ptr(),
|
||||||
|
self.end - (begin + length),
|
||||||
|
);
|
||||||
|
self.end = next_end;
|
||||||
|
}
|
||||||
|
Some(self.available_data())
|
||||||
|
}
|
||||||
|
|
||||||
|
//FIXME: this should probably be rewritten, and tested extensively
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub fn replace_slice(&mut self, data: &[u8], start: usize, length: usize) -> Option<usize> {
|
||||||
|
let data_len = data.len();
|
||||||
|
if start + length > self.available_data()
|
||||||
|
|| self.position + start + data_len > self.capacity
|
||||||
|
{
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let begin = self.position + start;
|
||||||
|
let slice_end = begin + data_len;
|
||||||
|
// we reduced the data size
|
||||||
|
if data_len < length {
|
||||||
|
ptr::copy(
|
||||||
|
data.as_ptr(),
|
||||||
|
(&mut self.memory[begin..slice_end]).as_mut_ptr(),
|
||||||
|
data_len,
|
||||||
|
);
|
||||||
|
|
||||||
|
ptr::copy(
|
||||||
|
(&self.memory[start + length..self.end]).as_ptr(),
|
||||||
|
(&mut self.memory[slice_end..]).as_mut_ptr(),
|
||||||
|
self.end - (start + length),
|
||||||
|
);
|
||||||
|
self.end = self.end - (length - data_len);
|
||||||
|
|
||||||
|
// we put more data in the buffer
|
||||||
|
} else {
|
||||||
|
ptr::copy(
|
||||||
|
(&self.memory[start + length..self.end]).as_ptr(),
|
||||||
|
(&mut self.memory[start + data_len..]).as_mut_ptr(),
|
||||||
|
self.end - (start + length),
|
||||||
|
);
|
||||||
|
ptr::copy(
|
||||||
|
data.as_ptr(),
|
||||||
|
(&mut self.memory[begin..slice_end]).as_mut_ptr(),
|
||||||
|
data_len,
|
||||||
|
);
|
||||||
|
self.end = self.end + data_len - length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(self.available_data())
|
||||||
|
}
|
||||||
|
|
||||||
|
//FIXME: this should probably be rewritten, and tested extensively
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub fn insert_slice(&mut self, data: &[u8], start: usize) -> Option<usize> {
|
||||||
|
let data_len = data.len();
|
||||||
|
if start > self.available_data() || self.position + self.end + data_len > self.capacity {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let begin = self.position + start;
|
||||||
|
let slice_end = begin + data_len;
|
||||||
|
ptr::copy(
|
||||||
|
(&self.memory[start..self.end]).as_ptr(),
|
||||||
|
(&mut self.memory[start + data_len..]).as_mut_ptr(),
|
||||||
|
self.end - start,
|
||||||
|
);
|
||||||
|
ptr::copy(
|
||||||
|
data.as_ptr(),
|
||||||
|
(&mut self.memory[begin..slice_end]).as_mut_ptr(),
|
||||||
|
data_len,
|
||||||
|
);
|
||||||
|
self.end = self.end + data_len;
|
||||||
|
}
|
||||||
|
Some(self.available_data())
|
||||||
}
|
}
|
||||||
Some(self.available_data())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Write for Buffer {
|
impl Write for Buffer {
|
||||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||||
match self.space().write(buf) {
|
match self.space().write(buf) {
|
||||||
Ok(size) => { self.fill(size); Ok(size) },
|
Ok(size) => {
|
||||||
err => err
|
self.fill(size);
|
||||||
|
Ok(size)
|
||||||
|
}
|
||||||
|
err => err,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fn flush(&mut self) -> io::Result<()> {
|
fn flush(&mut self) -> io::Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Read for Buffer {
|
impl Read for Buffer {
|
||||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||||
let len = cmp::min(self.available_data(), buf.len());
|
let len = cmp::min(self.available_data(), buf.len());
|
||||||
unsafe {
|
unsafe {
|
||||||
ptr::copy((&self.memory[self.position..self.position+len]).as_ptr(), buf.as_mut_ptr(), len);
|
ptr::copy(
|
||||||
self.position += len;
|
(&self.memory[self.position..self.position + len]).as_ptr(),
|
||||||
|
buf.as_mut_ptr(),
|
||||||
|
len,
|
||||||
|
);
|
||||||
|
self.position += len;
|
||||||
|
}
|
||||||
|
Ok(len)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl BufMut for Buffer {
|
||||||
|
fn remaining_mut(&self) -> usize {
|
||||||
|
self.available_space()
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn advance_mut(&mut self, cnt: usize) {
|
||||||
|
self.fill(cnt);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn chunk_mut(&mut self) -> &mut bytes::buf::UninitSlice {
|
||||||
|
self.space().into()
|
||||||
}
|
}
|
||||||
Ok(len)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn fill_and_consume() {
|
fn fill_and_consume() {
|
||||||
let mut b = Buffer::with_capacity(10);
|
let mut b = Buffer::with_capacity(10);
|
||||||
assert_eq!(b.available_data(), 0);
|
assert_eq!(b.available_data(), 0);
|
||||||
assert_eq!(b.available_space(), 10);
|
assert_eq!(b.available_space(), 10);
|
||||||
let res = b.write(&b"abcd"[..]);
|
let res = b.write(&b"abcd"[..]);
|
||||||
assert_eq!(res.ok(), Some(4));
|
assert_eq!(res.ok(), Some(4));
|
||||||
assert_eq!(b.available_data(), 4);
|
assert_eq!(b.available_data(), 4);
|
||||||
assert_eq!(b.available_space(), 6);
|
assert_eq!(b.available_space(), 6);
|
||||||
|
|
||||||
assert_eq!(b.data(), &b"abcd"[..]);
|
assert_eq!(b.data(), &b"abcd"[..]);
|
||||||
|
|
||||||
b.consume(2);
|
b.consume(2);
|
||||||
assert_eq!(b.available_data(), 2);
|
assert_eq!(b.available_data(), 2);
|
||||||
assert_eq!(b.available_space(), 6);
|
assert_eq!(b.available_space(), 6);
|
||||||
assert_eq!(b.data(), &b"cd"[..]);
|
assert_eq!(b.data(), &b"cd"[..]);
|
||||||
|
|
||||||
b.shift();
|
b.shift();
|
||||||
assert_eq!(b.available_data(), 2);
|
assert_eq!(b.available_data(), 2);
|
||||||
assert_eq!(b.available_space(), 8);
|
assert_eq!(b.available_space(), 8);
|
||||||
assert_eq!(b.data(), &b"cd"[..]);
|
assert_eq!(b.data(), &b"cd"[..]);
|
||||||
|
|
||||||
assert_eq!(b.write(&b"efghijklmnop"[..]).ok(), Some(8));
|
assert_eq!(b.write(&b"efghijklmnop"[..]).ok(), Some(8));
|
||||||
assert_eq!(b.available_data(), 10);
|
assert_eq!(b.available_data(), 10);
|
||||||
assert_eq!(b.available_space(), 0);
|
assert_eq!(b.available_space(), 0);
|
||||||
assert_eq!(b.data(), &b"cdefghijkl"[..]);
|
assert_eq!(b.data(), &b"cdefghijkl"[..]);
|
||||||
b.shift();
|
b.shift();
|
||||||
assert_eq!(b.available_data(), 10);
|
assert_eq!(b.available_data(), 10);
|
||||||
assert_eq!(b.available_space(), 0);
|
assert_eq!(b.available_space(), 0);
|
||||||
assert_eq!(b.data(), &b"cdefghijkl"[..]);
|
assert_eq!(b.data(), &b"cdefghijkl"[..]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn delete() {
|
fn delete() {
|
||||||
let mut b = Buffer::with_capacity(10);
|
let mut b = Buffer::with_capacity(10);
|
||||||
let _ = b.write(&b"abcdefgh"[..]);
|
let _ = b.write(&b"abcdefgh"[..]);
|
||||||
assert_eq!(b.available_data(), 8);
|
assert_eq!(b.available_data(), 8);
|
||||||
assert_eq!(b.available_space(), 2);
|
assert_eq!(b.available_space(), 2);
|
||||||
|
|
||||||
assert_eq!(b.delete_slice(2, 3), Some(5));
|
assert_eq!(b.delete_slice(2, 3), Some(5));
|
||||||
assert_eq!(b.available_data(), 5);
|
assert_eq!(b.available_data(), 5);
|
||||||
assert_eq!(b.available_space(), 5);
|
assert_eq!(b.available_space(), 5);
|
||||||
assert_eq!(b.data(), &b"abfgh"[..]);
|
assert_eq!(b.data(), &b"abfgh"[..]);
|
||||||
|
|
||||||
assert_eq!(b.delete_slice(5, 2), None);
|
assert_eq!(b.delete_slice(5, 2), None);
|
||||||
assert_eq!(b.delete_slice(4, 2), None);
|
assert_eq!(b.delete_slice(4, 2), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn replace() {
|
fn replace() {
|
||||||
let mut b = Buffer::with_capacity(10);
|
let mut b = Buffer::with_capacity(10);
|
||||||
let _ = b.write(&b"abcdefgh"[..]);
|
let _ = b.write(&b"abcdefgh"[..]);
|
||||||
assert_eq!(b.available_data(), 8);
|
assert_eq!(b.available_data(), 8);
|
||||||
assert_eq!(b.available_space(), 2);
|
assert_eq!(b.available_space(), 2);
|
||||||
|
|
||||||
assert_eq!(b.replace_slice(&b"ABC"[..], 2, 3), Some(8));
|
assert_eq!(b.replace_slice(&b"ABC"[..], 2, 3), Some(8));
|
||||||
assert_eq!(b.available_data(), 8);
|
assert_eq!(b.available_data(), 8);
|
||||||
assert_eq!(b.available_space(), 2);
|
assert_eq!(b.available_space(), 2);
|
||||||
assert_eq!(b.data(), &b"abABCfgh"[..]);
|
assert_eq!(b.data(), &b"abABCfgh"[..]);
|
||||||
|
|
||||||
assert_eq!(b.replace_slice(&b"XYZ"[..], 8, 3), None);
|
assert_eq!(b.replace_slice(&b"XYZ"[..], 8, 3), None);
|
||||||
assert_eq!(b.replace_slice(&b"XYZ"[..], 6, 3), None);
|
assert_eq!(b.replace_slice(&b"XYZ"[..], 6, 3), None);
|
||||||
|
|
||||||
assert_eq!(b.replace_slice(&b"XYZ"[..], 2, 4), Some(7));
|
assert_eq!(b.replace_slice(&b"XYZ"[..], 2, 4), Some(7));
|
||||||
assert_eq!(b.available_data(), 7);
|
assert_eq!(b.available_data(), 7);
|
||||||
assert_eq!(b.available_space(), 3);
|
assert_eq!(b.available_space(), 3);
|
||||||
assert_eq!(b.data(), &b"abXYZgh"[..]);
|
assert_eq!(b.data(), &b"abXYZgh"[..]);
|
||||||
|
|
||||||
assert_eq!(b.replace_slice(&b"123"[..], 2, 2), Some(8));
|
assert_eq!(b.replace_slice(&b"123"[..], 2, 2), Some(8));
|
||||||
assert_eq!(b.available_data(), 8);
|
assert_eq!(b.available_data(), 8);
|
||||||
assert_eq!(b.available_space(), 2);
|
assert_eq!(b.available_space(), 2);
|
||||||
assert_eq!(b.data(), &b"ab123Zgh"[..]);
|
assert_eq!(b.data(), &b"ab123Zgh"[..]);
|
||||||
}
|
}
|
||||||
|
|
||||||
use std::str;
|
use std::str;
|
||||||
#[test]
|
#[test]
|
||||||
fn set_position() {
|
fn set_position() {
|
||||||
let mut output = [0;5];
|
let mut output = [0; 5];
|
||||||
let mut b = Buffer::with_capacity(10);
|
let mut b = Buffer::with_capacity(10);
|
||||||
let _ = b.write(&b"abcdefgh"[..]);
|
let _ = b.write(&b"abcdefgh"[..]);
|
||||||
let _ = b.read(&mut output);
|
let _ = b.read(&mut output);
|
||||||
assert_eq!(b.available_data(), 3);
|
assert_eq!(b.available_data(), 3);
|
||||||
println!("{:?}", b.position());
|
println!("{:?}", b.position());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn consume_without_shift() {
|
fn consume_without_shift() {
|
||||||
let mut b = Buffer::with_capacity(10);
|
let mut b = Buffer::with_capacity(10);
|
||||||
let _ = b.write(&b"abcdefgh"[..]);
|
let _ = b.write(&b"abcdefgh"[..]);
|
||||||
b.consume_noshift(6);
|
b.consume_noshift(6);
|
||||||
assert_eq!(b.position(), 6);
|
assert_eq!(b.position(), 6);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue