Skip to content

Commit 0398977

Browse files
wedsonafojeda
authored andcommitted
rust: alloc: introduce the VecExt trait
Make `try_with_capacity`, `try_push`, and `try_extend_from_slice` methods available in `Vec` even though it doesn't implement them. It is implemented with `try_reserve` and `push_within_capacity`. This is in preparation for switching to the upstream `alloc` crate. Reviewed-by: Benno Lossin <[email protected]> Suggested-by: Gary Guo <[email protected]> Signed-off-by: Wedson Almeida Filho <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Miguel Ojeda <[email protected]>
1 parent 31d94d8 commit 0398977

File tree

4 files changed

+52
-0
lines changed

4 files changed

+52
-0
lines changed

rust/kernel/alloc.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@
55
#[cfg(not(test))]
66
#[cfg(not(testlib))]
77
mod allocator;
8+
pub mod vec_ext;

rust/kernel/alloc/vec_ext.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
//! Extensions to [`Vec`] for fallible allocations.
4+
5+
use alloc::{collections::TryReserveError, vec::Vec};
6+
use core::result::Result;
7+
8+
/// Extensions to [`Vec`].
9+
pub trait VecExt<T>: Sized {
10+
/// Creates a new [`Vec`] instance with at least the given capacity.
11+
fn try_with_capacity(capacity: usize) -> Result<Self, TryReserveError>;
12+
13+
/// Appends an element to the back of the [`Vec`] instance.
14+
fn try_push(&mut self, v: T) -> Result<(), TryReserveError>;
15+
16+
/// Pushes clones of the elements of slice into the [`Vec`] instance.
17+
fn try_extend_from_slice(&mut self, other: &[T]) -> Result<(), TryReserveError>
18+
where
19+
T: Clone;
20+
}
21+
22+
impl<T> VecExt<T> for Vec<T> {
23+
fn try_with_capacity(capacity: usize) -> Result<Self, TryReserveError> {
24+
let mut v = Vec::new();
25+
v.try_reserve(capacity)?;
26+
Ok(v)
27+
}
28+
29+
fn try_push(&mut self, v: T) -> Result<(), TryReserveError> {
30+
if let Err(retry) = self.push_within_capacity(v) {
31+
self.try_reserve(1)?;
32+
let _ = self.push_within_capacity(retry);
33+
}
34+
Ok(())
35+
}
36+
37+
fn try_extend_from_slice(&mut self, other: &[T]) -> Result<(), TryReserveError>
38+
where
39+
T: Clone,
40+
{
41+
self.try_reserve(other.len())?;
42+
for item in other {
43+
self.try_push(item.clone())?;
44+
}
45+
46+
Ok(())
47+
}
48+
}

rust/kernel/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#![feature(new_uninit)]
1919
#![feature(receiver_trait)]
2020
#![feature(unsize)]
21+
#![feature(vec_push_within_capacity)]
2122

2223
// Ensure conditional compilation based on the kernel configuration works;
2324
// otherwise we may silently break things like initcall handling.

rust/kernel/prelude.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
#[doc(no_inline)]
1515
pub use core::pin::Pin;
1616

17+
pub use crate::alloc::vec_ext::VecExt;
18+
1719
#[doc(no_inline)]
1820
pub use alloc::{boxed::Box, vec::Vec};
1921

0 commit comments

Comments
 (0)