Skip to content
This repository was archived by the owner on Feb 14, 2023. It is now read-only.

Add Buffer::resize and Buffer::truncate. #16

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/buffer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ impl BufImpl {

pub fn reserve(&mut self, additional: usize)[additional] -> bool;

pub fn resize(&mut self, new_len: usize, value: u8)[new_len, value] -> bool;

pub fn make_room(&mut self)[];

pub fn buf(&self)[] -> &[u8];
Expand All @@ -111,5 +113,7 @@ impl BufImpl {
pub unsafe fn bytes_written(&mut self, add: usize)[add];

pub fn consume(&mut self, amt: usize)[amt];

pub fn truncate(&mut self, len: usize)[len];
}
}
9 changes: 9 additions & 0 deletions src/buffer/slice_deque_buf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ impl SliceDequeBuf {
true
}

pub fn resize(&mut self, new_len: usize, value: u8) -> bool {
self.deque.resize(new_len, value);
true
}

/// This method is a no-op.
pub fn make_room(&mut self) {}

Expand Down Expand Up @@ -80,4 +85,8 @@ impl SliceDequeBuf {
self.deque.move_head(offset);
}
}

pub fn truncate(&mut self, len: usize) {
self.deque.truncate_back(len);
}
}
115 changes: 115 additions & 0 deletions src/buffer/std_buf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,25 @@ impl StdBuf {
self.buf.reserve(additional - usable_space)
}

pub fn resize(&mut self, new_len: usize, value: u8) -> bool {
if new_len <= self.len() {
self.truncate(new_len);
false
} else {
let additional = new_len - self.len();
let res = self.reserve(additional);

unsafe {
for x in &mut self.buf.as_mut_slice()[self.end .. self.end + additional] {
*x = value;
}
}

self.end += additional;
res
}
}

pub fn make_room(&mut self) {
self.check_cursors();

Expand Down Expand Up @@ -104,6 +123,11 @@ impl StdBuf {
self.check_cursors();
}

pub fn truncate(&mut self, len: usize) {
self.end = cmp::min(self.pos + len, self.end);
self.check_cursors();
}

pub fn check_cursors(&mut self) -> bool {
if self.pos == self.end {
self.pos = 0;
Expand Down Expand Up @@ -233,3 +257,94 @@ fn read_into_full() {
assert_eq!(buffer.read_from(&mut bytes).unwrap(), 1);
assert_eq!(buffer.read_from(&mut bytes).unwrap(), 0);
}

#[test]
fn test_truncate() {
use Buffer;
let mut buffer = Buffer::with_capacity(32);

buffer.truncate(5);
assert_eq!(buffer.len(), 0);

buffer.push_bytes(&[1, 2, 3, 4, 5, 6, 7]);
assert_eq!(buffer.len(), 7);

buffer.truncate(10);
assert_eq!(buffer.len(), 7);

buffer.truncate(7);
assert_eq!(buffer.len(), 7);

buffer.truncate(5);
assert_eq!(buffer.len(), 5);
assert_eq!(buffer.buf(), &[1, 2, 3, 4, 5]);

buffer.consume(1);
buffer.truncate(3);
assert_eq!(buffer.len(), 3);
assert_eq!(buffer.buf(), &[2, 3, 4]);

buffer.truncate(0);
assert_eq!(buffer.len(), 0);
}

#[test]
fn test_resize() {
use Buffer;
let mut buffer = Buffer::with_capacity(10);

buffer.resize(10, 0);
assert_eq!(buffer.len(), 10);
assert_eq!(buffer.capacity(), 10);
assert_eq!(buffer.buf(), &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);

buffer.resize(11, 1);
assert_eq!(buffer.len(), 11);
assert_eq!(buffer.capacity(), 11);
assert_eq!(buffer.buf(), &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]);

buffer.resize(5, 2);
assert_eq!(buffer.len(), 5);
assert_eq!(buffer.capacity(), 11);
assert_eq!(buffer.buf(), &[0, 0, 0, 0, 0]);

buffer.resize(7, 3);
assert_eq!(buffer.len(), 7);
assert_eq!(buffer.capacity(), 11);
assert_eq!(buffer.buf(), &[0, 0, 0, 0, 0, 3, 3]);
assert_eq!(buffer.usable_space(), 4);
assert_eq!(buffer.free_space(), 4);

buffer.consume(2);
buffer.resize(7, 4);
assert_eq!(buffer.len(), 7);
assert_eq!(buffer.capacity(), 11);
assert_eq!(buffer.buf(), &[0, 0, 0, 3, 3, 4, 4]);
assert_eq!(buffer.usable_space(), 2);
assert_eq!(buffer.free_space(), 4);

buffer.resize(11, 5);
assert_eq!(buffer.len(), 11);
assert_eq!(buffer.capacity(), 13);
assert_eq!(buffer.buf(), &[0, 0, 0, 3, 3, 4, 4, 5, 5, 5, 5]);
assert_eq!(buffer.usable_space(), 0);
assert_eq!(buffer.free_space(), 2);

buffer.make_room();
assert_eq!(buffer.usable_space(), 2);
assert_eq!(buffer.free_space(), 2);

buffer.resize(13, 6);
assert_eq!(buffer.len(), 13);
assert_eq!(buffer.capacity(), 13);
assert_eq!(buffer.buf(), &[0, 0, 0, 3, 3, 4, 4, 5, 5, 5, 5, 6, 6]);
assert_eq!(buffer.usable_space(), 0);
assert_eq!(buffer.free_space(), 0);

buffer.resize(0, 7);
assert_eq!(buffer.len(), 0);
assert_eq!(buffer.capacity(), 13);
assert_eq!(buffer.buf(), &[]);
assert_eq!(buffer.usable_space(), 13);
assert_eq!(buffer.free_space(), 13);
}
32 changes: 32 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1012,6 +1012,31 @@ impl Buffer {
}
}

/// Resizes the buffer in-place sto that `len` is equal to `new_len`.
///
/// If `new_len` is greater than `len`, the buffer is extended by the difference,
/// with each additional slot filled with `value`. If `new_len` is less than `len`,
/// the buffer is simply truncated.
///
/// Note that this will reallocate even if there is enough free space at the head of
/// the buffer if `len() + usable_space() < new_len`.
///
/// If you prefer copying data down in the buffer before attempting to reallocate
/// you may wish to call `.make_room()` first.
pub fn resize(&mut self, new_len: usize, value: u8) {
// Returns `true` if we reallocated out-of-place and thus need to re-zero.
if self.buf.resize(new_len, value) {
self.zeroed = 0;
}
}

/// Resizes the buffer in-place sto that `len` is equal to `new_len`.
///
/// Same as calling `.resize(new_len, 0)`.
pub fn resize_default(&mut self, new_len: usize) {
self.buf.resize(new_len, 0);
}

/// Get an immutable slice of the available bytes in this buffer.
///
/// Call `.consume()` to remove bytes from the beginning of this slice.
Expand Down Expand Up @@ -1175,6 +1200,13 @@ impl Buffer {
self.buf.consume(amt);
}

/// Shortens the buffer, keeping the first `len`.
///
/// If `len` is greater then buffer's length, this has no effect.
pub fn truncate(&mut self, len: usize) {
self.buf.truncate(len);
}

/// Empty this buffer by consuming all bytes.
pub fn clear(&mut self) {
let buf_len = self.len();
Expand Down