//! Simple heap-allocated vector. #![cfg(feature = "alloc")] #![doc(hidden)] use crate::bigint; #[cfg(not(feature = "std"))] use alloc::vec::Vec; use core::{cmp, ops}; #[cfg(feature = "std")] use std::vec::Vec; /// Simple heap vector implementation. #[derive(Clone)] pub struct HeapVec { /// The heap-allocated buffer for the elements. data: Vec, } #[allow(clippy::new_without_default)] impl HeapVec { /// Construct an empty vector. #[inline] pub fn new() -> Self { Self { data: Vec::with_capacity(bigint::BIGINT_LIMBS), } } /// Construct a vector from an existing slice. #[inline] pub fn try_from(x: &[bigint::Limb]) -> Option { let mut vec = Self::new(); vec.try_extend(x)?; Some(vec) } /// Sets the length of a vector. /// /// This will explicitly set the size of the vector, without actually /// modifying its buffers, so it is up to the caller to ensure that the /// vector is actually the specified size. /// /// # Safety /// /// Safe as long as `len` is less than `self.capacity()` and has been initialized. #[inline] pub unsafe fn set_len(&mut self, len: usize) { debug_assert!(len <= bigint::BIGINT_LIMBS); unsafe { self.data.set_len(len) }; } /// The number of elements stored in the vector. #[inline] pub fn len(&self) -> usize { self.data.len() } /// If the vector is empty. #[inline] pub fn is_empty(&self) -> bool { self.len() == 0 } /// The number of items the vector can hold. #[inline] pub fn capacity(&self) -> usize { self.data.capacity() } /// Append an item to the vector. #[inline] pub fn try_push(&mut self, value: bigint::Limb) -> Option<()> { self.data.push(value); Some(()) } /// Remove an item from the end of the vector and return it, or None if empty. #[inline] pub fn pop(&mut self) -> Option { self.data.pop() } /// Copy elements from a slice and append them to the vector. #[inline] pub fn try_extend(&mut self, slc: &[bigint::Limb]) -> Option<()> { self.data.extend_from_slice(slc); Some(()) } /// Try to resize the buffer. /// /// If the new length is smaller than the current length, truncate /// the input. If it's larger, then append elements to the buffer. #[inline] pub fn try_resize(&mut self, len: usize, value: bigint::Limb) -> Option<()> { self.data.resize(len, value); Some(()) } // HI /// Get the high 64 bits from the vector. #[inline(always)] pub fn hi64(&self) -> (u64, bool) { bigint::hi64(&self.data) } // FROM /// Create StackVec from u64 value. #[inline(always)] pub fn from_u64(x: u64) -> Self { bigint::from_u64(x) } // MATH /// Normalize the integer, so any leading zero values are removed. #[inline] pub fn normalize(&mut self) { bigint::normalize(self) } /// Get if the big integer is normalized. #[inline] pub fn is_normalized(&self) -> bool { bigint::is_normalized(self) } /// AddAssign small integer. #[inline] pub fn add_small(&mut self, y: bigint::Limb) -> Option<()> { bigint::small_add(self, y) } /// MulAssign small integer. #[inline] pub fn mul_small(&mut self, y: bigint::Limb) -> Option<()> { bigint::small_mul(self, y) } } impl PartialEq for HeapVec { #[inline] #[allow(clippy::op_ref)] fn eq(&self, other: &Self) -> bool { use core::ops::Deref; self.len() == other.len() && self.deref() == other.deref() } } impl Eq for HeapVec { } impl cmp::PartialOrd for HeapVec { #[inline] fn partial_cmp(&self, other: &Self) -> Option { Some(bigint::compare(self, other)) } } impl cmp::Ord for HeapVec { #[inline] fn cmp(&self, other: &Self) -> cmp::Ordering { bigint::compare(self, other) } } impl ops::Deref for HeapVec { type Target = [bigint::Limb]; #[inline] fn deref(&self) -> &[bigint::Limb] { &self.data } } impl ops::DerefMut for HeapVec { #[inline] fn deref_mut(&mut self) -> &mut [bigint::Limb] { &mut self.data } } impl ops::MulAssign<&[bigint::Limb]> for HeapVec { #[inline] fn mul_assign(&mut self, rhs: &[bigint::Limb]) { bigint::large_mul(self, rhs).unwrap(); } }