#[cfg(all(feature = "alloc", not(feature = "std")))]
use alloc::vec::Vec;
use core::{fmt, iter, mem, ops, slice};
use super::Field;
use crate::primitives::correction::NO_ALLOC_MAX_LENGTH;
#[derive(PartialEq, Eq, Clone, Debug, Hash)]
pub struct FieldVec<F> {
inner_a: [F; NO_ALLOC_MAX_LENGTH],
len: usize,
#[cfg(feature = "alloc")]
inner_v: Vec<F>,
}
impl<F> FieldVec<F> {
#[inline]
pub fn has_data(&self) -> bool { self.len <= NO_ALLOC_MAX_LENGTH || cfg!(feature = "alloc") }
#[inline]
pub fn assert_has_data(&self) {
assert!(
self.has_data(),
"checksums of {} characters (more than {}) require the `alloc` feature of `bech32` to be enabled",
self.len,
NO_ALLOC_MAX_LENGTH,
);
}
#[inline]
pub fn len(&self) -> usize { self.len }
#[inline]
pub fn is_empty(&self) -> bool { self.len == 0 }
pub fn reverse(&mut self) {
self.assert_has_data();
#[cfg(not(feature = "alloc"))]
{
self.inner_a[..self.len].reverse();
}
#[cfg(feature = "alloc")]
if self.len > NO_ALLOC_MAX_LENGTH {
self.inner_v.reverse();
} else {
self.inner_a[..self.len].reverse();
}
}
pub fn iter(&self) -> slice::Iter<'_, F> {
if self.len > NO_ALLOC_MAX_LENGTH {
self.assert_has_data();
#[cfg(feature = "alloc")]
return self.inner_v[..self.len].iter();
}
self.inner_a[..self.len].iter()
}
pub fn iter_mut(&mut self) -> slice::IterMut<'_, F> {
if self.len > NO_ALLOC_MAX_LENGTH {
self.assert_has_data();
#[cfg(feature = "alloc")]
return self.inner_v[..self.len].iter_mut();
}
self.inner_a[..self.len].iter_mut()
}
}
impl<F: Field> FieldVec<F> {
#[inline]
pub fn from_powers(elem: F, n: usize) -> Self {
iter::successors(Some(F::ONE), |gen| Some(elem.clone() * gen)).take(n + 1).collect()
}
#[inline]
pub fn mul_assign_pointwise(&mut self, other: &Self) {
assert_eq!(self.len, other.len, "cannot add vectors of different lengths");
for (i, fe) in self.iter_mut().enumerate() {
*fe *= &other[i];
}
}
#[inline]
pub fn mul_pointwise(mut self, other: &Self) -> Self {
self.mul_assign_pointwise(other);
self
}
#[inline]
pub fn lift<E: Field + From<F>>(&self) -> FieldVec<E> {
self.iter().cloned().map(E::from).collect()
}
}
impl<F: Default> Default for FieldVec<F> {
fn default() -> Self { Self::new() }
}
impl<F: Default> FieldVec<F> {
pub fn new() -> Self {
FieldVec {
inner_a: Default::default(),
len: 0,
#[cfg(feature = "alloc")]
inner_v: Vec::new(),
}
}
pub fn with_capacity(cap: usize) -> Self {
#[cfg(not(feature = "alloc"))]
{
let mut ret = Self::new();
ret.len = cap;
ret.assert_has_data();
ret.len = 0;
ret
}
#[cfg(feature = "alloc")]
if cap > NO_ALLOC_MAX_LENGTH {
let mut ret = Self::new();
ret.inner_v = Vec::with_capacity(cap);
ret
} else {
Self::new()
}
}
pub fn push_back(&mut self, item: F) { self.push(item) }
pub fn push(&mut self, item: F) {
self.len += 1;
self.assert_has_data();
#[cfg(not(feature = "alloc"))]
{
self.inner_a[self.len - 1] = item;
}
#[cfg(feature = "alloc")]
if self.len < NO_ALLOC_MAX_LENGTH + 1 {
self.inner_a[self.len - 1] = item;
} else {
if self.len == NO_ALLOC_MAX_LENGTH + 1 {
let inner_a = mem::take(&mut self.inner_a);
self.inner_v = inner_a.into();
}
self.inner_v.push(item);
}
}
pub fn pop_front(&mut self) -> Option<F> {
self.assert_has_data();
if self.len == 0 {
return None;
}
#[cfg(not(feature = "alloc"))]
{
self.reverse();
let ret = self.pop();
self.reverse();
ret
}
#[cfg(feature = "alloc")]
if self.len > NO_ALLOC_MAX_LENGTH + 1 {
self.len -= 1;
Some(self.inner_v.remove(0))
} else {
self.reverse();
let ret = self.pop();
self.reverse();
ret
}
}
pub fn pop(&mut self) -> Option<F> {
self.assert_has_data();
if self.len == 0 {
return None;
}
self.len -= 1;
#[cfg(not(feature = "alloc"))]
{
Some(mem::take(&mut self.inner_a[self.len]))
}
#[cfg(feature = "alloc")]
if self.len < NO_ALLOC_MAX_LENGTH {
Some(mem::take(&mut self.inner_a[self.len]))
} else {
use core::convert::TryFrom;
let ret = self.inner_v.pop();
let inner_v = mem::take(&mut self.inner_v);
match <[F; NO_ALLOC_MAX_LENGTH]>::try_from(inner_v) {
Ok(arr) => self.inner_a = arr,
Err(vec) => self.inner_v = vec,
}
ret
}
}
}
impl<F: Clone + Default> iter::FromIterator<F> for FieldVec<F> {
fn from_iter<I>(iter: I) -> Self
where
I: IntoIterator<Item = F>,
{
let mut iter = iter.into_iter();
let mut inner_a = [(); NO_ALLOC_MAX_LENGTH].map(|_| F::default());
let mut len = 0;
for elem in iter.by_ref().take(NO_ALLOC_MAX_LENGTH) {
inner_a[len] = elem;
len += 1;
}
#[allow(unused_variables)]
if let Some(next) = iter.next() {
#[cfg(feature = "alloc")]
{
let mut inner_v = inner_a.to_vec();
inner_v.push(next);
inner_v.extend(iter);
Self { inner_a, len: inner_v.len(), inner_v }
}
#[cfg(not(feature = "alloc"))]
{
Self { len: inner_a.len() + 1 + iter.count(), inner_a }
}
} else {
Self {
inner_a,
len,
#[cfg(feature = "alloc")]
inner_v: Vec::default(),
}
}
}
}
impl<F: fmt::Display> fmt::Display for FieldVec<F> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
for fe in self.iter() {
fe.fmt(f)?;
}
Ok(())
}
}
impl<'a, F> IntoIterator for &'a FieldVec<F> {
type Item = &'a F;
type IntoIter = slice::Iter<'a, F>;
#[inline]
fn into_iter(self) -> Self::IntoIter { self.iter() }
}
impl<'a, F> IntoIterator for &'a mut FieldVec<F> {
type Item = &'a mut F;
type IntoIter = slice::IterMut<'a, F>;
#[inline]
fn into_iter(self) -> Self::IntoIter { self.iter_mut() }
}
impl<F> ops::Index<usize> for FieldVec<F> {
type Output = F;
fn index(&self, index: usize) -> &F {
if self.len() > NO_ALLOC_MAX_LENGTH {
self.assert_has_data();
#[cfg(feature = "alloc")]
return &self.inner_v[..self.len][index];
}
&self.inner_a[..self.len][index]
}
}
impl<F> ops::Index<ops::Range<usize>> for FieldVec<F> {
type Output = [F];
fn index(&self, index: ops::Range<usize>) -> &[F] {
if self.len() > NO_ALLOC_MAX_LENGTH {
self.assert_has_data();
#[cfg(feature = "alloc")]
return &self.inner_v[..self.len][index];
}
&self.inner_a[..self.len][index]
}
}
impl<F> ops::Index<ops::RangeFrom<usize>> for FieldVec<F> {
type Output = [F];
fn index(&self, index: ops::RangeFrom<usize>) -> &[F] {
if self.len() > NO_ALLOC_MAX_LENGTH {
self.assert_has_data();
#[cfg(feature = "alloc")]
return &self.inner_v[..self.len][index];
}
&self.inner_a[..self.len][index]
}
}
impl<F> ops::Index<ops::RangeTo<usize>> for FieldVec<F> {
type Output = [F];
fn index(&self, index: ops::RangeTo<usize>) -> &[F] {
if self.len() > NO_ALLOC_MAX_LENGTH {
self.assert_has_data();
#[cfg(feature = "alloc")]
return &self.inner_v[..self.len][index];
}
&self.inner_a[..self.len][index]
}
}
impl<F> ops::Index<ops::RangeFull> for FieldVec<F> {
type Output = [F];
fn index(&self, index: ops::RangeFull) -> &[F] {
if self.len() > NO_ALLOC_MAX_LENGTH {
self.assert_has_data();
#[cfg(feature = "alloc")]
return &self.inner_v[..self.len][index];
}
&self.inner_a[..self.len][index]
}
}
impl<F> ops::IndexMut<usize> for FieldVec<F> {
fn index_mut(&mut self, index: usize) -> &mut F {
if self.len() > NO_ALLOC_MAX_LENGTH {
self.assert_has_data();
#[cfg(feature = "alloc")]
return &mut self.inner_v[..self.len][index];
}
&mut self.inner_a[..self.len][index]
}
}
impl<F> ops::IndexMut<ops::Range<usize>> for FieldVec<F> {
fn index_mut(&mut self, index: ops::Range<usize>) -> &mut [F] {
if self.len() > NO_ALLOC_MAX_LENGTH {
self.assert_has_data();
#[cfg(feature = "alloc")]
return &mut self.inner_v[..self.len][index];
}
&mut self.inner_a[..self.len][index]
}
}
impl<F> ops::IndexMut<ops::RangeFrom<usize>> for FieldVec<F> {
fn index_mut(&mut self, index: ops::RangeFrom<usize>) -> &mut [F] {
if self.len() > NO_ALLOC_MAX_LENGTH {
self.assert_has_data();
#[cfg(feature = "alloc")]
return &mut self.inner_v[..self.len][index];
}
&mut self.inner_a[..self.len][index]
}
}
impl<F> ops::IndexMut<ops::RangeTo<usize>> for FieldVec<F> {
fn index_mut(&mut self, index: ops::RangeTo<usize>) -> &mut [F] {
if self.len() > NO_ALLOC_MAX_LENGTH {
self.assert_has_data();
#[cfg(feature = "alloc")]
return &mut self.inner_v[..self.len][index];
}
&mut self.inner_a[..self.len][index]
}
}
impl<F> ops::IndexMut<ops::RangeFull> for FieldVec<F> {
fn index_mut(&mut self, index: ops::RangeFull) -> &mut [F] {
if self.len() > NO_ALLOC_MAX_LENGTH {
self.assert_has_data();
#[cfg(feature = "alloc")]
return &mut self.inner_v[..self.len][index];
}
&mut self.inner_a[..self.len][index]
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{Fe1024, Fe32};
#[test]
fn push_pop() {
let mut x: FieldVec<_> = (0..NO_ALLOC_MAX_LENGTH).collect();
let x_1: FieldVec<_> = (0..NO_ALLOC_MAX_LENGTH - 1).collect();
assert_eq!(x.len(), NO_ALLOC_MAX_LENGTH);
assert!(!x.is_empty());
assert_eq!(x.pop(), Some(NO_ALLOC_MAX_LENGTH - 1));
assert_eq!(x, x_1);
x.push(NO_ALLOC_MAX_LENGTH - 1);
let mut y: FieldVec<_> = None.into_iter().collect();
for i in 0..NO_ALLOC_MAX_LENGTH {
y.push(i);
assert_eq!(y[i], i);
y[i] = i + 1;
assert_eq!(y[i], i + 1);
y[i] -= 1;
}
assert_eq!(x, y);
for i in (0..NO_ALLOC_MAX_LENGTH).rev() {
assert_eq!(y.pop(), Some(i));
}
assert_eq!(y.len(), 0);
assert!(y.is_empty());
}
#[test]
fn iter_slice() {
let mut x: FieldVec<_> = (0..NO_ALLOC_MAX_LENGTH).collect();
assert!(x.iter().copied().eq(0..NO_ALLOC_MAX_LENGTH));
assert!(x[..].iter().copied().eq(0..NO_ALLOC_MAX_LENGTH));
assert!(x[0..].iter().copied().eq(0..NO_ALLOC_MAX_LENGTH));
assert!(x[..NO_ALLOC_MAX_LENGTH].iter().copied().eq(0..NO_ALLOC_MAX_LENGTH));
assert!(x[1..].iter().copied().eq(1..NO_ALLOC_MAX_LENGTH));
assert!(x[..NO_ALLOC_MAX_LENGTH - 1].iter().copied().eq(0..NO_ALLOC_MAX_LENGTH - 1));
assert!(x[1..NO_ALLOC_MAX_LENGTH - 1].iter().copied().eq(1..NO_ALLOC_MAX_LENGTH - 1));
x[..].reverse();
assert!(x.iter().copied().eq((0..NO_ALLOC_MAX_LENGTH).rev()));
x[..NO_ALLOC_MAX_LENGTH].reverse();
assert!(x.iter().copied().eq(0..NO_ALLOC_MAX_LENGTH));
x[0..].reverse();
assert!(x.iter().copied().eq((0..NO_ALLOC_MAX_LENGTH).rev()));
x[0..NO_ALLOC_MAX_LENGTH].reverse();
assert!(x.iter().copied().eq(0..NO_ALLOC_MAX_LENGTH));
for elem in x.iter_mut() {
*elem += 1;
}
assert!(x.iter().copied().eq(1..NO_ALLOC_MAX_LENGTH + 1));
}
#[test]
fn field_ops() {
let qs: FieldVec<_> = FieldVec::from_powers(Fe32::Q, NO_ALLOC_MAX_LENGTH - 1);
let ps: FieldVec<_> = FieldVec::from_powers(Fe32::P, NO_ALLOC_MAX_LENGTH - 1);
let pzr: FieldVec<_> = FieldVec::from_powers(Fe32::Z, 3);
assert_eq!(qs.len(), NO_ALLOC_MAX_LENGTH);
assert_eq!(ps.len(), NO_ALLOC_MAX_LENGTH);
assert_eq!(pzr.len(), 4);
let pzr = pzr.lift::<Fe32>();
assert!(qs.iter().copied().eq(Some(Fe32::P)
.into_iter()
.chain(iter::repeat(Fe32::Q).take(NO_ALLOC_MAX_LENGTH - 1))));
assert!(ps.iter().copied().eq(iter::repeat(Fe32::P).take(NO_ALLOC_MAX_LENGTH)));
assert_eq!(pzr.iter().copied().collect::<Vec<_>>(), [Fe32::P, Fe32::Z, Fe32::Y, Fe32::G,]);
let pow2 = pzr.clone().mul_pointwise(&pzr);
assert_eq!(pow2.iter().copied().collect::<Vec<_>>(), [Fe32::P, Fe32::Y, Fe32::S, Fe32::J,]);
let lifted = pzr.lift::<Fe1024>();
assert_eq!(
lifted.iter().copied().collect::<Vec<_>>(),
[
Fe1024::from(Fe32::P),
Fe1024::from(Fe32::Z),
Fe1024::from(Fe32::Y),
Fe1024::from(Fe32::G),
]
);
}
#[test]
fn construct_too_far() {
let x: FieldVec<_> = (0..NO_ALLOC_MAX_LENGTH + 1).collect();
let y: FieldVec<_> = FieldVec::from_powers(Fe32::Q, NO_ALLOC_MAX_LENGTH);
assert_eq!(x.len(), NO_ALLOC_MAX_LENGTH + 1);
assert_eq!(y.len(), NO_ALLOC_MAX_LENGTH + 1);
}
#[test]
#[cfg_attr(not(feature = "alloc"), should_panic)]
fn access_too_far() {
let x: FieldVec<_> = (0..NO_ALLOC_MAX_LENGTH + 1).collect();
let _ = x[0];
}
#[test]
#[cfg_attr(not(feature = "alloc"), should_panic)]
fn push_too_far() {
let mut x: FieldVec<_> = (0..NO_ALLOC_MAX_LENGTH).collect();
x.push(100);
}
#[test]
#[cfg(feature = "alloc")]
fn alloc_boundary_ops() {
let n = NO_ALLOC_MAX_LENGTH + 1;
let mut small: FieldVec<_> = (0..NO_ALLOC_MAX_LENGTH).collect();
small.reverse();
assert_eq!(small[0], NO_ALLOC_MAX_LENGTH - 1);
let mut at_max: FieldVec<_> = (0..NO_ALLOC_MAX_LENGTH).collect();
assert_eq!(at_max.pop_front(), Some(0));
assert_eq!(at_max.len(), NO_ALLOC_MAX_LENGTH - 1);
let mut v: FieldVec<_> = (0..n).collect();
assert_eq!(v.len(), n);
assert_eq!(v[0], 0);
assert_eq!(v[n - 1], n - 1);
v.reverse();
assert_eq!(v[0], n - 1);
assert_eq!(v[n - 1], 0);
v.reverse();
assert_eq!(v.pop(), Some(n - 1));
assert_eq!(v.len(), NO_ALLOC_MAX_LENGTH);
v.push(n - 1);
v.push(n);
assert_eq!(v.len(), n + 1);
assert_eq!(v.pop_front(), Some(0));
assert_eq!(v.len(), n);
}
#[test]
fn basic_fieldvec_ops() {
let mut v: FieldVec<Fe32> = [Fe32::P, Fe32::Z, Fe32::R].iter().copied().collect();
assert!(!v.to_string().is_empty());
assert_eq!(v.pop_front(), Some(Fe32::P));
assert_eq!(v.pop_front(), Some(Fe32::Z));
assert_eq!(v.pop_front(), Some(Fe32::R));
assert_eq!(v.pop_front(), None);
v.push_back(Fe32::A);
v.push_back(Fe32::K);
assert_eq!(v.pop_front(), Some(Fe32::A));
let mut nums: FieldVec<_> = (0..3usize).collect();
for elem in &mut nums {
*elem += 10;
}
assert_eq!(nums[2], 12);
}
#[test]
fn small_vec_range_indexing() {
let mut v: FieldVec<_> = (0..3usize).collect();
assert_eq!(&v[0..2], &[0, 1]);
for elem in v[..].iter_mut() {
*elem += 10;
}
assert_eq!(&v[..], &[10, 11, 12]);
}
#[test]
#[cfg(feature = "alloc")]
fn large_vec_range_indexing() {
let n = NO_ALLOC_MAX_LENGTH + 2;
let mut v: FieldVec<_> = (0..n).collect();
for elem in v[NO_ALLOC_MAX_LENGTH..n].iter_mut() {
*elem += 100;
}
assert_eq!(v[NO_ALLOC_MAX_LENGTH], NO_ALLOC_MAX_LENGTH + 100);
assert_eq!(v[n - 1], n - 1 + 100);
let mut v: FieldVec<_> = (0..n).collect();
for elem in v[NO_ALLOC_MAX_LENGTH..].iter_mut() {
*elem += 200;
}
assert_eq!(v[NO_ALLOC_MAX_LENGTH], NO_ALLOC_MAX_LENGTH + 200);
assert_eq!(v[n - 1], n - 1 + 200);
let mut v: FieldVec<_> = (0..n).collect();
for elem in v[..2].iter_mut() {
*elem += 300;
}
assert_eq!(v[0], 300);
assert_eq!(v[1], 301);
assert_eq!(v[n - 1], n - 1);
}
}