Skip to content

Commit be66b4e

Browse files
committed
grow_to is implemented
Increases the capacity of the vector at least up to the `new_capacity`: * has no affect if `new_capacity <= self.capacity()`, and returns `Ok(self.capacity())`; * increases the capacity to `x >= new_capacity` otherwise if the operation succeeds. This method is unsafe due to the internal guarantees of pinned vectors. * A `SplitVec`, on the other hand, can grow to the `new_capacity` without any problem. However, it is not designed to have intermediate empty fragments, while `grow_to` can leave such fragments. Hence, the caller is responsible for handling this.
1 parent f7f50cd commit be66b4e

File tree

3 files changed

+93
-4
lines changed

3 files changed

+93
-4
lines changed

Cargo.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "orx-split-vec"
3-
version = "2.5.0"
3+
version = "2.6.0"
44
edition = "2021"
55
authors = ["orxfun <[email protected]>"]
66
description = "An efficient constant access time vector with dynamic capacity and pinned elements."
@@ -10,7 +10,7 @@ keywords = ["vec", "array", "split", "fragments", "pinned"]
1010
categories = ["data-structures", "rust-patterns"]
1111

1212
[dependencies]
13-
orx-pinned-vec = "2.4"
13+
orx-pinned-vec = "2.5"
1414

1515
[[bench]]
1616
name = "serial_access"

src/pinned_vec.rs

+58
Original file line numberDiff line numberDiff line change
@@ -575,6 +575,20 @@ where
575575
Ok(self.capacity())
576576
}
577577
}
578+
579+
unsafe fn grow_to(&mut self, new_capacity: usize) -> Result<usize, PinnedVecGrowthError> {
580+
if new_capacity <= self.capacity() {
581+
Ok(self.capacity())
582+
} else {
583+
let mut current_capacity = self.capacity();
584+
while new_capacity > current_capacity {
585+
let new_fragment_capacity = self.add_fragment_get_fragment_capacity();
586+
current_capacity += new_fragment_capacity;
587+
}
588+
debug_assert_eq!(current_capacity, self.capacity());
589+
Ok(current_capacity)
590+
}
591+
}
578592
}
579593

580594
#[cfg(test)]
@@ -955,4 +969,48 @@ mod tests {
955969
}
956970
test_all_growth_types!(test);
957971
}
972+
973+
#[test]
974+
fn grow_to_under_capacity() {
975+
fn test<G: Growth>(mut vec: SplitVec<usize, G>) {
976+
for _ in 0..10 {
977+
assert_eq!(Ok(vec.capacity()), unsafe { vec.grow_to(0) });
978+
assert_eq!(Ok(vec.capacity()), unsafe {
979+
vec.grow_to(vec.capacity() - 1)
980+
});
981+
assert_eq!(Ok(vec.capacity()), unsafe { vec.grow_to(vec.capacity()) });
982+
}
983+
}
984+
test_all_growth_types!(test);
985+
}
986+
987+
#[test]
988+
fn grow_to() {
989+
fn test<G: Growth>(mut vec: SplitVec<usize, G>) {
990+
for _ in 0..10 {
991+
let expected_capacity =
992+
vec.capacity() + vec.growth.new_fragment_capacity(vec.fragments());
993+
let expected_num_fragments = vec.fragments().len() + 1;
994+
995+
assert_eq!(Ok(expected_capacity), unsafe {
996+
vec.grow_to(vec.capacity() + 1)
997+
});
998+
999+
assert_eq!(vec.fragments().len(), expected_num_fragments);
1000+
assert_eq!(vec.capacity(), expected_capacity);
1001+
}
1002+
1003+
vec.clear();
1004+
1005+
for _ in 0..10 {
1006+
let prev_num_fragments = vec.fragments().len();
1007+
1008+
let new_capacity = unsafe { vec.grow_to(vec.capacity() + 1000) }.expect("is-okay");
1009+
1010+
assert!(vec.fragments().len() >= prev_num_fragments);
1011+
assert_eq!(vec.capacity(), new_capacity);
1012+
}
1013+
}
1014+
test_all_growth_types!(test);
1015+
}
9581016
}

src/split_vec.rs

+33-2
Original file line numberDiff line numberDiff line change
@@ -134,10 +134,17 @@ where
134134
.unwrap_or(false)
135135
}
136136

137+
/// Adds a new fragment to fragments of the split vector.
137138
pub(crate) fn add_fragment(&mut self) {
138-
let capacity = self.growth.new_fragment_capacity(&self.fragments);
139-
let new_fragment = Fragment::new(capacity);
139+
self.add_fragment_get_fragment_capacity();
140+
}
141+
142+
/// Adds a new fragment and return the capacity of the added (now last) fragment.
143+
pub(crate) fn add_fragment_get_fragment_capacity(&mut self) -> usize {
144+
let new_fragment_capacity = self.growth.new_fragment_capacity(&self.fragments);
145+
let new_fragment = Fragment::new(new_fragment_capacity);
140146
self.fragments.push(new_fragment);
147+
new_fragment_capacity
141148
}
142149

143150
pub(crate) fn add_fragment_with_first_value(&mut self, first_value: T) {
@@ -225,4 +232,28 @@ mod tests {
225232
test(SplitVec::with_doubling_growth());
226233
test(SplitVec::with_linear_growth(6));
227234
}
235+
236+
#[test]
237+
fn add_fragment() {
238+
fn test<G: Growth>(mut vec: SplitVec<usize, G>) {
239+
for _ in 0..10 {
240+
let expected_new_fragment_cap = vec.growth.new_fragment_capacity(&vec.fragments);
241+
let new_fragment_cap = vec.add_fragment_get_fragment_capacity();
242+
assert_eq!(expected_new_fragment_cap, new_fragment_cap);
243+
}
244+
245+
vec.clear();
246+
247+
let mut expected_capacity = vec.capacity();
248+
for _ in 0..2 {
249+
let expected_new_fragment_cap = vec.growth.new_fragment_capacity(&vec.fragments);
250+
expected_capacity += expected_new_fragment_cap;
251+
vec.add_fragment();
252+
}
253+
254+
assert_eq!(expected_capacity, vec.capacity());
255+
}
256+
257+
test_all_growth_types!(test);
258+
}
228259
}

0 commit comments

Comments
 (0)