diff options
author | Miguel Ojeda <ojeda@kernel.org> | 2023-02-24 18:11:50 +0900 |
---|---|---|
committer | Miguel Ojeda <ojeda@kernel.org> | 2023-04-10 23:55:43 +0200 |
commit | 318c3cc8e107c2b36108132057ca90d0d56d1bd9 (patch) | |
tree | c794f8b17ba3e4920809d372b1912859720c5cb7 /rust/alloc/vec/spec_extend.rs | |
parent | 3dcb652a3afc4b32cf8d3c1605c8cf22ad174a07 (diff) | |
download | linux-318c3cc8e107c2b36108132057ca90d0d56d1bd9.tar.gz linux-318c3cc8e107c2b36108132057ca90d0d56d1bd9.tar.bz2 linux-318c3cc8e107c2b36108132057ca90d0d56d1bd9.zip |
rust: alloc: vec: Add some try_* methods we need
Add some missing fallible methods that we need.
They are all marked as:
#[stable(feature = "kernel", since = "1.0.0")]
for easy identification.
Lina: Extracted from commit 487d7578bd03 ("rust: alloc: add some `try_*`
methods we need") in rust-for-linux/rust.
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
Signed-off-by: Asahi Lina <lina@asahilina.net>
Link: https://github.com/Rust-for-Linux/linux/commit/487d7578bd03
Link: https://lore.kernel.org/r/20230224-rust-vec-v1-4-733b5b5a57c5@asahilina.net
[ Match the non-fallible methods from version 1.62.0, since those
in commit 487d7578bd03 were written for 1.54.0-beta.1. ]
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
Diffstat (limited to 'rust/alloc/vec/spec_extend.rs')
-rw-r--r-- | rust/alloc/vec/spec_extend.rs | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/rust/alloc/vec/spec_extend.rs b/rust/alloc/vec/spec_extend.rs index 7bb3abb7ee71..5ce2d00991bc 100644 --- a/rust/alloc/vec/spec_extend.rs +++ b/rust/alloc/vec/spec_extend.rs @@ -1,6 +1,7 @@ // SPDX-License-Identifier: Apache-2.0 OR MIT use crate::alloc::Allocator; +use crate::collections::{TryReserveError, TryReserveErrorKind}; use core::iter::TrustedLen; use core::ptr::{self}; use core::slice::{self}; @@ -8,10 +9,17 @@ use core::slice::{self}; use super::{IntoIter, SetLenOnDrop, Vec}; // Specialization trait used for Vec::extend +#[cfg(not(no_global_oom_handling))] pub(super) trait SpecExtend<T, I> { fn spec_extend(&mut self, iter: I); } +// Specialization trait used for Vec::try_extend +pub(super) trait TrySpecExtend<T, I> { + fn try_spec_extend(&mut self, iter: I) -> Result<(), TryReserveError>; +} + +#[cfg(not(no_global_oom_handling))] impl<T, I, A: Allocator> SpecExtend<T, I> for Vec<T, A> where I: Iterator<Item = T>, @@ -21,6 +29,16 @@ where } } +impl<T, I, A: Allocator> TrySpecExtend<T, I> for Vec<T, A> +where + I: Iterator<Item = T>, +{ + default fn try_spec_extend(&mut self, iter: I) -> Result<(), TryReserveError> { + self.try_extend_desugared(iter) + } +} + +#[cfg(not(no_global_oom_handling))] impl<T, I, A: Allocator> SpecExtend<T, I> for Vec<T, A> where I: TrustedLen<Item = T>, @@ -59,6 +77,41 @@ where } } +impl<T, I, A: Allocator> TrySpecExtend<T, I> for Vec<T, A> +where + I: TrustedLen<Item = T>, +{ + default fn try_spec_extend(&mut self, iterator: I) -> Result<(), TryReserveError> { + // This is the case for a TrustedLen iterator. + let (low, high) = iterator.size_hint(); + if let Some(additional) = high { + debug_assert_eq!( + low, + additional, + "TrustedLen iterator's size hint is not exact: {:?}", + (low, high) + ); + self.try_reserve(additional)?; + unsafe { + let mut ptr = self.as_mut_ptr().add(self.len()); + let mut local_len = SetLenOnDrop::new(&mut self.len); + iterator.for_each(move |element| { + ptr::write(ptr, element); + ptr = ptr.offset(1); + // Since the loop executes user code which can panic we have to bump the pointer + // after each step. + // NB can't overflow since we would have had to alloc the address space + local_len.increment_len(1); + }); + } + Ok(()) + } else { + Err(TryReserveErrorKind::CapacityOverflow.into()) + } + } +} + +#[cfg(not(no_global_oom_handling))] impl<T, A: Allocator> SpecExtend<T, IntoIter<T>> for Vec<T, A> { fn spec_extend(&mut self, mut iterator: IntoIter<T>) { unsafe { @@ -68,6 +121,17 @@ impl<T, A: Allocator> SpecExtend<T, IntoIter<T>> for Vec<T, A> { } } +impl<T, A: Allocator> TrySpecExtend<T, IntoIter<T>> for Vec<T, A> { + fn try_spec_extend(&mut self, mut iterator: IntoIter<T>) -> Result<(), TryReserveError> { + unsafe { + self.try_append_elements(iterator.as_slice() as _)?; + } + iterator.forget_remaining_elements(); + Ok(()) + } +} + +#[cfg(not(no_global_oom_handling))] impl<'a, T: 'a, I, A: Allocator + 'a> SpecExtend<&'a T, I> for Vec<T, A> where I: Iterator<Item = &'a T>, @@ -78,6 +142,17 @@ where } } +impl<'a, T: 'a, I, A: Allocator + 'a> TrySpecExtend<&'a T, I> for Vec<T, A> +where + I: Iterator<Item = &'a T>, + T: Clone, +{ + default fn try_spec_extend(&mut self, iterator: I) -> Result<(), TryReserveError> { + self.try_spec_extend(iterator.cloned()) + } +} + +#[cfg(not(no_global_oom_handling))] impl<'a, T: 'a, A: Allocator + 'a> SpecExtend<&'a T, slice::Iter<'a, T>> for Vec<T, A> where T: Copy, @@ -87,3 +162,13 @@ where unsafe { self.append_elements(slice) }; } } + +impl<'a, T: 'a, A: Allocator + 'a> TrySpecExtend<&'a T, slice::Iter<'a, T>> for Vec<T, A> +where + T: Copy, +{ + fn try_spec_extend(&mut self, iterator: slice::Iter<'a, T>) -> Result<(), TryReserveError> { + let slice = iterator.as_slice(); + unsafe { self.try_append_elements(slice) } + } +} |