//! Utilities used throughout the library. use alloc::{alloc::Allocator, collections::TryReserveError, vec::Vec}; #[cfg(feature = "core-fmt")] use core::fmt; #[cfg(feature = "core-error")] use core::error; /// Extension trait for handling OOM conditions better with a [`Vec`]. pub trait VecMemoryExt { /// Appends an element to the back of the vector. /// /// # Errors /// /// This method errors if the capacity overflows or if the allocator /// reports a failure. fn try_push(&mut self, value: T) -> Result<(), TryReserveError>; } impl VecMemoryExt for Vec where A: Allocator, { fn try_push(&mut self, value: T) -> Result<(), TryReserveError> { self.try_reserve(1)?; //SAFETY: we just reserved space for this element unsafe { self.push_within_capacity(value).unwrap_unchecked() }; Ok(()) } } /// Extension trait for wrapping arithmetic. pub const trait WrappingArithmeticExt { /// Wrapping integer increment. fn wrapping_increment(self) -> Self; /// Mutable wrapping integer increment. fn wrapping_increment_mut(&mut self); /// Wrapping integer decrement. fn wrapping_decrement(self) -> Self; /// Mutable wrapping integer decrement. fn wrapping_decrement_mut(&mut self); } macro_rules! wrapping_arithmetic_ext_impl { ($t:ty) => { impl const WrappingArithmeticExt for $t { fn wrapping_increment(self) -> Self { self.wrapping_add(1) } fn wrapping_increment_mut(&mut self) { *self = self.wrapping_add(1); } fn wrapping_decrement(self) -> Self { self.wrapping_sub(1) } fn wrapping_decrement_mut(&mut self) { *self = self.wrapping_sub(1); } } }; } wrapping_arithmetic_ext_impl!(usize); wrapping_arithmetic_ext_impl!(u64); wrapping_arithmetic_ext_impl!(u32); wrapping_arithmetic_ext_impl!(u16); wrapping_arithmetic_ext_impl!(u8); wrapping_arithmetic_ext_impl!(isize); wrapping_arithmetic_ext_impl!(i64); wrapping_arithmetic_ext_impl!(i32); wrapping_arithmetic_ext_impl!(i16); wrapping_arithmetic_ext_impl!(i8); /// Extension trait for checked arithmetic that turns the output into a /// [`Result`]. pub const trait CheckedArithmeticExt: Sized { /// Checked integer addition. /// /// # Errors /// /// Returns an error if the result would have overflowed. fn errored_add(self, rhs: Self) -> Result; /// Checked integer decrement. /// /// # Errors /// /// Returns an error if the result would have overflowed. fn errored_decrement(self) -> Result; /// Checked integer division. /// /// # Errors /// /// Returns an error if the result would have overflowed. fn errored_div(self, rhs: Self) -> Result; /// Checked integer increment. /// /// # Errors /// /// Returns an error if the result would have overflowed. fn errored_increment(self) -> Result; /// Checked integer multiplication. /// /// # Errors /// /// Returns an error if the result would have overflowed. fn errored_mul(self, rhs: Self) -> Result; /// Checked integer remainder. /// /// # Errors /// /// Returns an error if the result would have overflowed. fn errored_rem(self, rhs: Self) -> Result; /// Checked integer subtraction. /// /// # Errors /// /// Returns an error if the result would have overflowed. fn errored_sub(self, rhs: Self) -> Result; } macro_rules! checked_arithmetic_ext_impl { ($t:ty) => { impl const CheckedArithmeticExt for $t { fn errored_add( self, rhs: Self, ) -> Result { self.checked_add(rhs).ok_or(IntegerOverflowError) } fn errored_decrement(self) -> Result { self.errored_sub(1) } fn errored_div( self, rhs: Self, ) -> Result { self.checked_div(rhs).ok_or(IntegerOverflowError) } fn errored_increment(self) -> Result { self.errored_add(1) } fn errored_mul( self, rhs: Self, ) -> Result { self.checked_mul(rhs).ok_or(IntegerOverflowError) } fn errored_rem( self, rhs: Self, ) -> Result { self.checked_rem(rhs).ok_or(IntegerOverflowError) } fn errored_sub( self, rhs: Self, ) -> Result { self.checked_sub(rhs).ok_or(IntegerOverflowError) } } }; } checked_arithmetic_ext_impl!(usize); checked_arithmetic_ext_impl!(u64); checked_arithmetic_ext_impl!(u32); checked_arithmetic_ext_impl!(u16); checked_arithmetic_ext_impl!(u8); checked_arithmetic_ext_impl!(isize); checked_arithmetic_ext_impl!(i64); checked_arithmetic_ext_impl!(i32); checked_arithmetic_ext_impl!(i16); checked_arithmetic_ext_impl!(i8); /// Representation of an integer overflow error. #[derive(Copy, Clone, PartialEq, Eq)] #[cfg_attr(feature = "core-fmt", derive(Debug))] pub struct IntegerOverflowError; #[cfg(feature = "core-fmt")] impl fmt::Display for IntegerOverflowError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str("integer overflow") } } #[cfg(feature = "core-error")] impl error::Error for IntegerOverflowError {}