Skip to content

Commit 9ead02e

Browse files
authored
Add truncate and resize methods to our OOM-handling Vec (#12583)
1 parent e367cd3 commit 9ead02e

2 files changed

Lines changed: 42 additions & 0 deletions

File tree

crates/core/src/alloc/vec.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::alloc::{TryClone, try_realloc};
22
use crate::error::OutOfMemory;
3+
use core::cmp::Ordering;
34
use core::marker::PhantomData;
45
use core::{
56
fmt, mem,
@@ -108,6 +109,34 @@ impl<T> Vec<T> {
108109
self.inner.pop()
109110
}
110111

112+
/// Same as [`std::vec::Vec::truncate`].
113+
pub fn truncate(&mut self, len: usize) {
114+
self.inner.truncate(len);
115+
}
116+
117+
/// Same as [`std::vec::Vec::resize`] but returns an error on allocation
118+
/// failure.
119+
pub fn resize(&mut self, new_len: usize, value: T) -> Result<(), OutOfMemory>
120+
where
121+
T: TryClone,
122+
{
123+
match new_len.cmp(&self.len()) {
124+
Ordering::Less => self.truncate(new_len),
125+
Ordering::Equal => {}
126+
Ordering::Greater => {
127+
let delta = new_len - self.len();
128+
self.reserve(delta)?;
129+
// Minimize `try_clone` calls by always pushing `value` directly
130+
// as the last element.
131+
for _ in 0..delta - 1 {
132+
self.push(value.try_clone()?)?;
133+
}
134+
self.push(value)?;
135+
}
136+
}
137+
Ok(())
138+
}
139+
111140
/// Same as [`std::vec::Vec::into_raw_parts`].
112141
pub fn into_raw_parts(mut self) -> (*mut T, usize, usize) {
113142
// NB: Can't use `Vec::into_raw_parts` until our MSRV is >= 1.93.

crates/fuzzing/tests/oom.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -708,6 +708,19 @@ fn vec_shrink_to_fit() -> Result<()> {
708708
Ok(())
709709
}
710710

711+
#[test]
712+
fn vec_resize() -> Result<()> {
713+
OomTest::new().test(|| {
714+
let mut v = Vec::new();
715+
v.resize(10, 'a')?; // Grow.
716+
v.resize(1, 'b')?; // Truncate.
717+
v.resize(1, 'c')?; // Same length.
718+
v.resize(3, 'd')?; // Grow again.
719+
assert_eq!(&*v, &['a', 'd', 'd']);
720+
Ok(())
721+
})
722+
}
723+
711724
#[test]
712725
fn vec_try_collect() -> Result<()> {
713726
OomTest::new().test(|| {

0 commit comments

Comments
 (0)