Vendor things
This commit is contained in:
parent
5deceec006
commit
977e3c17e5
19434 changed files with 10682014 additions and 0 deletions
308
third-party/vendor/minimal-lexical/src/stackvec.rs
vendored
Normal file
308
third-party/vendor/minimal-lexical/src/stackvec.rs
vendored
Normal file
|
|
@ -0,0 +1,308 @@
|
|||
//! Simple stack-allocated vector.
|
||||
|
||||
#![cfg(not(feature = "alloc"))]
|
||||
#![doc(hidden)]
|
||||
|
||||
use crate::bigint;
|
||||
use core::{cmp, mem, ops, ptr, slice};
|
||||
|
||||
/// Simple stack vector implementation.
|
||||
#[derive(Clone)]
|
||||
pub struct StackVec {
|
||||
/// The raw buffer for the elements.
|
||||
data: [mem::MaybeUninit<bigint::Limb>; bigint::BIGINT_LIMBS],
|
||||
/// The number of elements in the array (we never need more than u16::MAX).
|
||||
length: u16,
|
||||
}
|
||||
|
||||
#[allow(clippy::new_without_default)]
|
||||
impl StackVec {
|
||||
/// Construct an empty vector.
|
||||
#[inline]
|
||||
pub const fn new() -> Self {
|
||||
Self {
|
||||
length: 0,
|
||||
data: [mem::MaybeUninit::uninit(); bigint::BIGINT_LIMBS],
|
||||
}
|
||||
}
|
||||
|
||||
/// Construct a vector from an existing slice.
|
||||
#[inline]
|
||||
pub fn try_from(x: &[bigint::Limb]) -> Option<Self> {
|
||||
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 `BIGINT_LIMBS`.
|
||||
#[inline]
|
||||
pub unsafe fn set_len(&mut self, len: usize) {
|
||||
// Constant is `u16::MAX` for older Rustc versions.
|
||||
debug_assert!(len <= 0xffff);
|
||||
debug_assert!(len <= bigint::BIGINT_LIMBS);
|
||||
self.length = len as u16;
|
||||
}
|
||||
|
||||
/// The number of elements stored in the vector.
|
||||
#[inline]
|
||||
pub const fn len(&self) -> usize {
|
||||
self.length as usize
|
||||
}
|
||||
|
||||
/// If the vector is empty.
|
||||
#[inline]
|
||||
pub const fn is_empty(&self) -> bool {
|
||||
self.len() == 0
|
||||
}
|
||||
|
||||
/// The number of items the vector can hold.
|
||||
#[inline]
|
||||
pub const fn capacity(&self) -> usize {
|
||||
bigint::BIGINT_LIMBS as usize
|
||||
}
|
||||
|
||||
/// Append an item to the vector, without bounds checking.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Safe if `self.len() < self.capacity()`.
|
||||
#[inline]
|
||||
pub unsafe fn push_unchecked(&mut self, value: bigint::Limb) {
|
||||
debug_assert!(self.len() < self.capacity());
|
||||
// SAFETY: safe, capacity is less than the current size.
|
||||
unsafe {
|
||||
ptr::write(self.as_mut_ptr().add(self.len()), value);
|
||||
self.length += 1;
|
||||
}
|
||||
}
|
||||
|
||||
/// Append an item to the vector.
|
||||
#[inline]
|
||||
pub fn try_push(&mut self, value: bigint::Limb) -> Option<()> {
|
||||
if self.len() < self.capacity() {
|
||||
// SAFETY: safe, capacity is less than the current size.
|
||||
unsafe { self.push_unchecked(value) };
|
||||
Some(())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Remove an item from the end of a vector, without bounds checking.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Safe if `self.len() > 0`.
|
||||
#[inline]
|
||||
pub unsafe fn pop_unchecked(&mut self) -> bigint::Limb {
|
||||
debug_assert!(!self.is_empty());
|
||||
// SAFETY: safe if `self.length > 0`.
|
||||
// We have a trivial drop and copy, so this is safe.
|
||||
self.length -= 1;
|
||||
unsafe { ptr::read(self.as_mut_ptr().add(self.len())) }
|
||||
}
|
||||
|
||||
/// Remove an item from the end of the vector and return it, or None if empty.
|
||||
#[inline]
|
||||
pub fn pop(&mut self) -> Option<bigint::Limb> {
|
||||
if self.is_empty() {
|
||||
None
|
||||
} else {
|
||||
// SAFETY: safe, since `self.len() > 0`.
|
||||
unsafe { Some(self.pop_unchecked()) }
|
||||
}
|
||||
}
|
||||
|
||||
/// Add items from a slice to the vector, without bounds checking.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Safe if `self.len() + slc.len() <= self.capacity()`.
|
||||
#[inline]
|
||||
pub unsafe fn extend_unchecked(&mut self, slc: &[bigint::Limb]) {
|
||||
let index = self.len();
|
||||
let new_len = index + slc.len();
|
||||
debug_assert!(self.len() + slc.len() <= self.capacity());
|
||||
let src = slc.as_ptr();
|
||||
// SAFETY: safe if `self.len() + slc.len() <= self.capacity()`.
|
||||
unsafe {
|
||||
let dst = self.as_mut_ptr().add(index);
|
||||
ptr::copy_nonoverlapping(src, dst, slc.len());
|
||||
self.set_len(new_len);
|
||||
}
|
||||
}
|
||||
|
||||
/// Copy elements from a slice and append them to the vector.
|
||||
#[inline]
|
||||
pub fn try_extend(&mut self, slc: &[bigint::Limb]) -> Option<()> {
|
||||
if self.len() + slc.len() <= self.capacity() {
|
||||
// SAFETY: safe, since `self.len() + slc.len() <= self.capacity()`.
|
||||
unsafe { self.extend_unchecked(slc) };
|
||||
Some(())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Truncate vector to new length, dropping any items after `len`.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Safe as long as `len <= self.capacity()`.
|
||||
unsafe fn truncate_unchecked(&mut self, len: usize) {
|
||||
debug_assert!(len <= self.capacity());
|
||||
self.length = len as u16;
|
||||
}
|
||||
|
||||
/// Resize the buffer, without bounds checking.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Safe as long as `len <= self.capacity()`.
|
||||
#[inline]
|
||||
pub unsafe fn resize_unchecked(&mut self, len: usize, value: bigint::Limb) {
|
||||
debug_assert!(len <= self.capacity());
|
||||
let old_len = self.len();
|
||||
if len > old_len {
|
||||
// We have a trivial drop, so there's no worry here.
|
||||
// Just, don't set the length until all values have been written,
|
||||
// so we don't accidentally read uninitialized memory.
|
||||
|
||||
// SAFETY: safe if `len < self.capacity()`.
|
||||
let count = len - old_len;
|
||||
for index in 0..count {
|
||||
unsafe {
|
||||
let dst = self.as_mut_ptr().add(old_len + index);
|
||||
ptr::write(dst, value);
|
||||
}
|
||||
}
|
||||
self.length = len as u16;
|
||||
} else {
|
||||
// SAFETY: safe since `len < self.len()`.
|
||||
unsafe { self.truncate_unchecked(len) };
|
||||
}
|
||||
}
|
||||
|
||||
/// 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<()> {
|
||||
if len > self.capacity() {
|
||||
None
|
||||
} else {
|
||||
// SAFETY: safe, since `len <= self.capacity()`.
|
||||
unsafe { self.resize_unchecked(len, value) };
|
||||
Some(())
|
||||
}
|
||||
}
|
||||
|
||||
// HI
|
||||
|
||||
/// Get the high 64 bits from the vector.
|
||||
#[inline(always)]
|
||||
pub fn hi64(&self) -> (u64, bool) {
|
||||
bigint::hi64(self)
|
||||
}
|
||||
|
||||
// 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 StackVec {
|
||||
#[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 StackVec {
|
||||
}
|
||||
|
||||
impl cmp::PartialOrd for StackVec {
|
||||
#[inline]
|
||||
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
|
||||
Some(bigint::compare(self, other))
|
||||
}
|
||||
}
|
||||
|
||||
impl cmp::Ord for StackVec {
|
||||
#[inline]
|
||||
fn cmp(&self, other: &Self) -> cmp::Ordering {
|
||||
bigint::compare(self, other)
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::Deref for StackVec {
|
||||
type Target = [bigint::Limb];
|
||||
#[inline]
|
||||
fn deref(&self) -> &[bigint::Limb] {
|
||||
// SAFETY: safe since `self.data[..self.len()]` must be initialized
|
||||
// and `self.len() <= self.capacity()`.
|
||||
unsafe {
|
||||
let ptr = self.data.as_ptr() as *const bigint::Limb;
|
||||
slice::from_raw_parts(ptr, self.len())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::DerefMut for StackVec {
|
||||
#[inline]
|
||||
fn deref_mut(&mut self) -> &mut [bigint::Limb] {
|
||||
// SAFETY: safe since `self.data[..self.len()]` must be initialized
|
||||
// and `self.len() <= self.capacity()`.
|
||||
unsafe {
|
||||
let ptr = self.data.as_mut_ptr() as *mut bigint::Limb;
|
||||
slice::from_raw_parts_mut(ptr, self.len())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::MulAssign<&[bigint::Limb]> for StackVec {
|
||||
#[inline]
|
||||
fn mul_assign(&mut self, rhs: &[bigint::Limb]) {
|
||||
bigint::large_mul(self, rhs).unwrap();
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue