//! Implement Fallible Vec usesuper::TryClone; usecrate::TryReserveError; #[allow(unused_imports)] use alloc::alloc::{alloc, realloc, Layout}; use alloc::vec::Vec; use core::convert::TryInto as _;
#[cfg(feature = "unstable")] #[macro_export] /// macro trying to create a vec, return a /// Result<Vec<T>,TryReserveError>
macro_rules! try_vec {
($elem:expr; $n:expr) => (
$crate::vec::try_from_elem($elem, $n)
);
($($x:expr),*) => ( match <alloc::boxed::Box<_> as $crate::boxed::FallibleBox<_>>::try_new([$($x),*]) {
Err(e) => Err(e),
Ok(b) => Ok(<[_]>::into_vec(b)),
}
);
($($x:expr,)*) => ($crate::try_vec![$($x),*])
}
/// trait implementing all fallible methods on vec pubtrait FallibleVec<T> { /// see reserve fn try_reserve(&mutself, additional: usize) -> Result<(), TryReserveError>; /// see push fn try_push(&mutself, elem: T) -> Result<(), TryReserveError>; /// try push and give back ownership in case of error fn try_push_give_back(&mutself, elem: T) -> Result<(), (T, TryReserveError)>; /// see with capacity, (Self must be sized by the constraint of Result) fn try_with_capacity(capacity: usize) -> Result<Self, TryReserveError> where Self: core::marker::Sized; /// see insert fn try_insert(&mutself, index: usize, element: T) -> Result<(), (T, TryReserveError)>; /// see append fn try_append(&mutself, other: &mutSelf) -> Result<(), TryReserveError>; /// see resize, only works when the `value` implements Copy, otherwise, look at try_resize_no_copy fn try_resize(&mutself, new_len: usize, value: T) -> Result<(), TryReserveError> where
T: Copy + Clone; fn try_resize_with<F>(&mutself, new_len: usize, f: F) -> Result<(), TryReserveError> where
F: FnMut() -> T; /// resize the vec by trying to clone the value repeatingly fn try_resize_no_copy(&mutself, new_len: usize, value: T) -> Result<(), TryReserveError> where
T: TryClone; /// see resize, only works when the `value` implements Copy, otherwise, look at try_extend_from_slice_no_copy fn try_extend_from_slice(&mutself, other: &[T]) -> Result<(), TryReserveError> where
T: Copy + Clone; /// extend the vec by trying to clone the value in `other` fn try_extend_from_slice_no_copy(&mutself, other: &[T]) -> Result<(), TryReserveError> where
T: TryClone;
}
/// TryVec is a thin wrapper around alloc::vec::Vec to provide support for /// fallible allocation. /// /// See the crate documentation for more. #[derive(PartialEq)] pubstruct TryVec<T> {
inner: Vec<T>,
}
impl<T: Read> TryRead for Take<T> { /// This function reserves the upper limit of what `src` can generate before /// reading all bytes until EOF in this source, placing them into `buf`. If the /// allocation is unsuccessful, or reading from the source generates an error /// before reaching EOF, this will return an error. Otherwise, it will return /// the number of bytes read. /// /// Since `Take::limit()` may return a value greater than the number of bytes /// which can be read from the source, it's possible this function may fail /// in the allocation phase even though allocating the number of bytes available /// to read would have succeeded. In general, it is assumed that the callers /// have accurate knowledge of the number of bytes of interest and have created /// `src` accordingly. #[inline] fn try_read_to_end(&mutself, buf: &mut TryVec<u8>) -> io::Result<usize> {
try_read_up_to(self, self.limit(), buf)
}
}
/// Read up to `limit` bytes from `src`, placing them into `buf` and returning the /// number of bytes read. Space for `limit` additional bytes is reserved in `buf`, so /// this function will return an error if the allocation fails. pubfn try_read_up_to<R: Read>(
src: &mut R,
limit: u64,
buf: &mut TryVec<u8>,
) -> io::Result<usize> { let additional = limit
.try_into()
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
buf.reserve(additional)
.map_err(|_| io::Error::new(io::ErrorKind::Other, "reserve allocation failed"))?; let bytes_read = src.take(limit).read_to_end(&mut buf.inner)?;
Ok(bytes_read)
}
impl<T> TryExtend<T> for Vec<T> { /// Extend the vector by `n` values, using the given generator. fn try_extend_with<E: ExtendWith<T>>(
&mutself,
n: usize, mut value: E,
) -> Result<(), TryReserveError> { if needs_to_grow(self, n) {
vec_try_reserve_for_growth(self, n)?;
}
letmut local_len = self.len(); // Write all elements except the last one for _ in1..n {
core::ptr::write(ptr, value.next()?);
ptr = ptr.offset(1); // Increment the length in every step in case next() panics
local_len += 1; self.set_len(local_len);
}
if n > 0 { // We can write the last element directly without cloning needlessly
core::ptr::write(ptr, value.last());
local_len += 1; self.set_len(local_len);
}
impl<T> Truncate for Vec<T> { fn truncate(&mutself, len: usize) { let current_len = self.len(); unsafe { letmut ptr = self.as_mut_ptr().add(current_len); // Set the final length at the end, keeping in mind that // dropping an element might panic. Works around a missed // optimization, as seen in the following issue: // https://github.com/rust-lang/rust/issues/51802 letmut local_len = self.len();
// drop any extra elements for _ in len..current_len {
ptr = ptr.offset(-1);
core::ptr::drop_in_place(ptr);
local_len -= 1; self.set_len(local_len);
}
}
}
}
/// try creating a vec from an `elem` cloned `n` times, see std::from_elem #[cfg(feature = "unstable")] pubfn try_from_elem<T: TryClone>(elem: T, n: usize) -> Result<Vec<T>, TryReserveError> {
<T as SpecFromElem>::try_from_elem(elem, n)
}
#[test] fn try_clone_vec() { // let v: Vec<u8> = from_elem(1, 10); let v = vec![42; 100];
assert_eq!(v.try_clone().unwrap(), v);
}
#[test] fn try_clone_oom() { let layout = Layout::new::<u8>(); let v = unsafe { Vec::<u8>::from_raw_parts(alloc(layout), core::isize::MAX as usize, core::isize::MAX as usize) };
assert!(v.try_clone().is_err());
}
#[test] fn tryvec_try_clone_oom() { let layout = Layout::new::<u8>(); let inner = unsafe { Vec::<u8>::from_raw_parts(alloc(layout), core::isize::MAX as usize, core::isize::MAX as usize) }; let tv = TryVec { inner };
assert!(tv.try_clone().is_err());
}
// #[test] // fn try_out_of_mem() { // let v = try_vec![42_u8; 1000000000]; // assert_eq!(v.try_clone().unwrap(), v); // }
#[test] fn oom() { letmut vec: Vec<char> = Vec::new(); match FallibleVec::try_reserve(&mut vec, core::usize::MAX / std::mem::size_of::<char>()) {
Ok(_) => panic!("it should be OOM"),
_ => (),
} match FallibleVec::try_reserve(&mut vec, core::usize::MAX) {
Ok(_) => panic!("it should be OOM"),
_ => (),
}
}
#[test] fn tryvec_oom() { letmut vec: TryVec<char> = TryVec::new(); match vec.reserve(core::usize::MAX / std::mem::size_of::<char>()) {
Ok(_) => panic!("it should be OOM"),
_ => (),
} match vec.reserve(core::usize::MAX) {
Ok(_) => panic!("it should be OOM"),
_ => (),
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.