Skip to content

Commit

Permalink
add support for zero length HeaderVec
Browse files Browse the repository at this point in the history
Having a HeaderVec being zero length is mostly useless because it has to reallocated instanly
when anything becomes pushed. This clearly should be avoided!

Nevertheless supporting zero length takes out a corner-case and a potential panic and removes
the burden for users explicitly ensuring zero length HeaderVecs don't happen in
practice. Generally improving software reliability.
  • Loading branch information
cehteh committed Jan 18, 2025
1 parent 2b4fbf6 commit d3a5a6f
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 4 deletions.
8 changes: 4 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ impl<H, T> HeaderVec<H, T> {
}

pub fn with_capacity(capacity: usize, head: H) -> Self {
assert!(capacity > 0, "HeaderVec capacity cannot be 0");
// Allocate the initial memory, which is uninitialized.
let layout = Self::layout(capacity);
let ptr = unsafe { alloc::alloc::alloc(layout) } as *mut AlignedHeader<H, T>;
Expand Down Expand Up @@ -271,8 +270,6 @@ impl<H, T> HeaderVec<H, T> {
"requested capacity is less than current length"
);
let old_capacity = self.capacity();
debug_assert_ne!(old_capacity, 0, "capacity of 0 not yet supported");
debug_assert_ne!(requested_capacity, 0, "capacity of 0 not yet supported");

let new_capacity = if requested_capacity > old_capacity {
if exact {
Expand All @@ -281,11 +278,14 @@ impl<H, T> HeaderVec<H, T> {
} else if requested_capacity <= old_capacity * 2 {
// doubling the capacity is sufficient
old_capacity * 2
} else {
} else if old_capacity > 0 {
// requested more than twice as much space, reserve the next multiple of
// old_capacity that is greater than the requested capacity. This gives headroom
// for new inserts while not doubling the memory requirement with bulk requests
(requested_capacity / old_capacity + 1).saturating_mul(old_capacity)
} else {
// special case when we start at capacity 0
requested_capacity
}
} else if exact {
// exact shrinking
Expand Down
11 changes: 11 additions & 0 deletions tests/simple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,17 @@ struct TestA {
c: usize,
}

#[test]
fn test_empty() {
let mut v_empty = HeaderVec::with_capacity(0, TestA { a: 4, b: !0, c: 66 });

assert_eq!(0, v_empty.len());
assert_eq!(0, v_empty.capacity());
assert_eq!(0, v_empty.as_slice().len());

v_empty.extend_from_slice("the quick brown fox jumps over the lazy dog".as_bytes());
}

#[test]
fn test_head_array() {
let mut v_orig = HeaderVec::new(TestA { a: 4, b: !0, c: 66 });
Expand Down

0 comments on commit d3a5a6f

Please sign in to comment.