#[macro_export]
#[doc(hidden)]
macro_rules! _array_base {
($name:ident,$l:expr,$t:ty) => {
#[allow(non_camel_case_types)]
#[derive(Clone, Copy)]
pub struct $name(pub [$t; $l]);
impl $name {
#[cfg_attr(feature = "use_attributes", unsafe_hacspec($name))]
pub fn new() -> Self {
Self([<$t>::default(); $l])
}
#[cfg_attr(feature = "use_attributes", in_hacspec($name))]
pub fn length() -> usize {
$l
}
#[cfg_attr(feature = "use_attributes", unsafe_hacspec($name))]
pub fn from_array(v: [$t; $l]) -> Self {
Self(v.clone())
}
#[cfg_attr(feature = "use_attributes", not_hacspec($name))]
pub fn from_native_slice(v: &[$t]) -> Self {
debug_assert!(v.len() <= $l);
let mut tmp = [<$t>::default(); $l];
for i in 0..v.len() {
tmp[i] = v[i];
}
Self(tmp.clone())
}
}
impl $name {
#[cfg_attr(feature = "use_attributes", in_hacspec($name))]
pub fn from_slice<A: SeqTrait<$t>>(input: &A, start: usize, len: usize) -> Self {
let mut a = Self::new();
debug_assert!(len <= a.len(), "{} > {}", len, a.len());
a = a.update_slice(0, input, start, len);
a
}
#[cfg_attr(feature = "use_attributes", in_hacspec)]
pub fn concat<A: SeqTrait<$t>>(&self, next: &A) -> Seq<$t> {
let mut out = Seq::new(self.len() + next.len());
out = out.update_start(self);
out = out.update_slice(self.len(), next, 0, next.len());
out
}
#[cfg_attr(feature = "use_attributes", in_hacspec($name))]
pub fn from_slice_range<A: SeqTrait<$t>>(input: &A, r: Range<usize>) -> Self {
Self::from_slice(input, r.start, r.end - r.start)
}
#[cfg_attr(feature = "use_attributes", in_hacspec($name))]
pub fn slice(&self, start_out: usize, len: usize) -> Seq<$t> {
Seq::from_slice(self, start_out, len)
}
#[cfg_attr(feature = "use_attributes", in_hacspec($name))]
pub fn slice_range(&self, r: Range<usize>) -> Seq<$t> {
self.slice(r.start, r.end - r.start)
}
#[cfg_attr(feature = "use_attributes", in_hacspec($name))]
pub fn num_chunks(&self, chunk_size: usize) -> usize {
(self.len() + chunk_size - 1) / chunk_size
}
#[cfg_attr(feature = "use_attributes", in_hacspec($name))]
pub fn get_chunk_len(&self, chunk_size: usize, chunk_number: usize) -> usize {
let idx_start = chunk_size * chunk_number;
if idx_start + chunk_size > self.len() {
self.len() - idx_start
} else {
chunk_size
}
}
#[cfg_attr(feature = "use_attributes", in_hacspec($name))]
pub fn get_chunk(&self, chunk_size: usize, chunk_number: usize) -> (usize, Seq<$t>) {
let idx_start = chunk_size * chunk_number;
let len = self.get_chunk_len(chunk_size, chunk_number);
let out = self.slice(idx_start, len);
(len, out)
}
#[cfg_attr(feature = "use_attributes", in_hacspec($name))]
pub fn set_chunk<A: SeqTrait<$t>>(
self,
chunk_size: usize,
chunk_number: usize,
input: &A,
) -> Self {
let idx_start = chunk_size * chunk_number;
let len = self.get_chunk_len(chunk_size, chunk_number);
debug_assert!(
input.len() == len,
"the chunk length should match the input. got {}, expected {}",
input.len(),
len
);
self.update_slice(idx_start, input, 0, len)
}
}
impl Default for $name {
#[cfg_attr(feature = "use_attributes", in_hacspec($name))]
fn default() -> Self {
$name::new()
}
}
impl SeqTrait<$t> for $name {
#[cfg_attr(feature = "use_attributes", in_hacspec($name))]
fn create(x: usize) -> Self {
assert_eq!(x, $l);
Self::new()
}
#[cfg_attr(feature = "use_attributes", unsafe_hacspec($name))]
fn len(&self) -> usize {
$l
}
#[cfg_attr(feature = "use_attributes", not_hacspec($name))]
fn iter(&self) -> core::slice::Iter<$t> {
self.0.iter()
}
#[cfg_attr(feature = "use_attributes", in_hacspec($name))]
fn update_slice<A: SeqTrait<$t>>(
mut self,
start_out: usize,
v: &A,
start_in: usize,
len: usize,
) -> Self {
debug_assert!(self.len() >= start_out + len);
debug_assert!(v.len() >= start_in + len);
for i in 0..len {
self[start_out + i] = v[start_in + i];
}
self
}
#[cfg_attr(feature = "use_attributes", in_hacspec($name))]
fn update<A: SeqTrait<$t>>(self, start: usize, v: &A) -> Self {
let len = v.len();
self.update_slice(start, v, 0, len)
}
#[cfg_attr(feature = "use_attributes", in_hacspec($name))]
fn update_start<A: SeqTrait<$t>>(self, v: &A) -> Self {
let len = v.len();
self.update_slice(0, v, 0, len)
}
}
impl Index<usize> for $name {
type Output = $t;
#[cfg_attr(feature = "use_attributes", unsafe_hacspec($name))]
fn index(&self, i: usize) -> &$t {
&self.0[i]
}
}
impl IndexMut<usize> for $name {
#[cfg_attr(feature = "use_attributes", unsafe_hacspec($name))]
fn index_mut(&mut self, i: usize) -> &mut $t {
&mut self.0[i]
}
}
impl Index<u8> for $name {
type Output = $t;
#[cfg_attr(feature = "use_attributes", unsafe_hacspec($name))]
fn index(&self, i: u8) -> &$t {
&self.0[i as usize]
}
}
impl IndexMut<u8> for $name {
#[cfg_attr(feature = "use_attributes", not_hacspec($name))]
fn index_mut(&mut self, i: u8) -> &mut $t {
&mut self.0[i as usize]
}
}
impl Index<u32> for $name {
type Output = $t;
#[cfg_attr(feature = "use_attributes", unsafe_hacspec($name))]
fn index(&self, i: u32) -> &$t {
&self.0[i as usize]
}
}
impl IndexMut<u32> for $name {
#[cfg_attr(feature = "use_attributes", not_hacspec($name))]
fn index_mut(&mut self, i: u32) -> &mut $t {
&mut self.0[i as usize]
}
}
impl Index<i32> for $name {
type Output = $t;
#[cfg_attr(feature = "use_attributes", unsafe_hacspec($name))]
fn index(&self, i: i32) -> &$t {
&self.0[i as usize]
}
}
impl IndexMut<i32> for $name {
#[cfg_attr(feature = "use_attributes", not_hacspec($name))]
fn index_mut(&mut self, i: i32) -> &mut $t {
&mut self.0[i as usize]
}
}
impl Index<RangeFull> for $name {
type Output = [$t];
#[cfg_attr(feature = "use_attributes", unsafe_hacspec($name))]
fn index(&self, r: RangeFull) -> &[$t] {
&self.0[r]
}
}
impl $name {
#[cfg_attr(feature = "use_attributes", not_hacspec($name))]
pub fn from_vec(x: Vec<$t>) -> $name {
debug_assert_eq!(x.len(), $l);
let mut tmp = [<$t>::default(); $l];
for (i, e) in x.iter().enumerate() {
tmp[i] = *e;
}
$name(tmp.clone())
}
#[cfg_attr(feature = "use_attributes", in_hacspec($name))]
pub fn from_seq<T: SeqTrait<$t>>(x: &T) -> $name {
debug_assert_eq!(x.len(), $l);
let mut out = $name::new();
for i in 0..x.len() {
out[i] = x[i];
}
out
}
}
impl $name {
fn hex_string_to_vec(s: &str) -> Vec<$t> {
debug_assert!(s.len() % core::mem::size_of::<$t>() == 0);
let b: Result<Vec<$t>, ParseIntError> = (0..s.len())
.step_by(2)
.map(|i| u8::from_str_radix(&s[i..i + 2], 16).map(<$t>::from))
.collect();
b.expect("Error parsing hex string")
}
#[cfg_attr(feature = "use_attributes", unsafe_hacspec($name))]
pub fn from_hex(s: &str) -> $name {
let v = $name::hex_string_to_vec(s);
let mut o = $name::new();
debug_assert!(v.len() == $l);
for i in 0..$l {
o[i] = v[i]
}
o
}
}
};
}
#[macro_export]
macro_rules! generic_array {
($name:ident,$l:expr) => {
#[allow(non_camel_case_types)]
#[derive(Clone, Copy)]
pub struct $name<T>(pub [T; $l]);
impl<T: Numeric + Copy> $name<T> {
#[cfg_attr(feature = "use_attributes", unsafe_hacspec($name))]
pub fn new() -> Self {
Self([<T>::default(); $l])
}
#[cfg_attr(feature = "use_attributes", in_hacspec($name))]
pub fn length() -> usize {
$l
}
#[cfg_attr(feature = "use_attributes", unsafe_hacspec($name))]
pub fn from_array(v: [T; $l]) -> Self {
Self(v.clone())
}
#[cfg_attr(feature = "use_attributes", not_hacspec($name))]
pub fn from_native_slice(v: &[T]) -> Self {
debug_assert!(v.len() <= $l);
let mut tmp = [<T>::default(); $l];
for i in 0..v.len() {
tmp[i] = v[i];
}
Self(tmp.clone())
}
}
impl<T: Numeric + Copy> $name<T> {
#[cfg_attr(feature = "use_attributes", in_hacspec($name))]
pub fn from_slice<A: SeqTrait<T>>(input: &A, start: usize, len: usize) -> Self {
let mut a = Self::new();
debug_assert!(len <= a.len());
a = a.update_slice(0, input, start, len);
a
}
#[cfg_attr(feature = "use_attributes", in_hacspec)]
pub fn concat<A: SeqTrait<T>>(&self, next: &A) -> Seq<T> {
let mut out = Seq::new(self.len() + next.len());
out = out.update_start(self);
out = out.update_slice(self.len(), next, 0, next.len());
out
}
#[cfg_attr(feature = "use_attributes", in_hacspec($name))]
pub fn from_slice_range<A: SeqTrait<T>>(input: &A, r: Range<usize>) -> Self {
Self::from_slice(input, r.start, r.end - r.start)
}
#[cfg_attr(feature = "use_attributes", in_hacspec($name))]
pub fn slice(&self, start_out: usize, len: usize) -> Seq<T> {
Seq::from_slice(self, start_out, len)
}
#[cfg_attr(feature = "use_attributes", in_hacspec($name))]
pub fn slice_range(&self, r: Range<usize>) -> Seq<T> {
self.slice(r.start, r.end - r.start)
}
#[cfg_attr(feature = "use_attributes", in_hacspec($name))]
pub fn num_chunks(&self, chunk_size: usize) -> usize {
(self.len() + chunk_size - 1) / chunk_size
}
#[cfg_attr(feature = "use_attributes", in_hacspec($name))]
pub fn get_chunk_len(&self, chunk_size: usize, chunk_number: usize) -> usize {
let idx_start = chunk_size * chunk_number;
if idx_start + chunk_size > self.len() {
self.len() - idx_start
} else {
chunk_size
}
}
#[cfg_attr(feature = "use_attributes", in_hacspec($name))]
pub fn get_chunk(&self, chunk_size: usize, chunk_number: usize) -> (usize, Seq<T>) {
let idx_start = chunk_size * chunk_number;
let len = self.get_chunk_len(chunk_size, chunk_number);
let out = self.slice(idx_start, len);
(len, out)
}
#[cfg_attr(feature = "use_attributes", in_hacspec($name))]
pub fn set_chunk<A: SeqTrait<T>>(
self,
chunk_size: usize,
chunk_number: usize,
input: &A,
) -> Self {
let idx_start = chunk_size * chunk_number;
let len = self.get_chunk_len(chunk_size, chunk_number);
debug_assert!(
input.len() == len,
"the chunk length should match the input. got {}, expected {}",
input.len(),
len
);
self.update_slice(idx_start, input, 0, len)
}
}
impl<T: Numeric + Copy> Default for $name<T> {
#[cfg_attr(feature = "use_attributes", in_hacspec($name))]
fn default() -> Self {
$name::new()
}
}
impl<T: Numeric + Copy> SeqTrait<T> for $name<T> {
#[cfg_attr(feature = "use_attributes", in_hacspec($name))]
fn create(x: usize) -> Self {
assert_eq!(x, $l);
Self::new()
}
#[cfg_attr(feature = "use_attributes", unsafe_hacspec($name))]
fn len(&self) -> usize {
$l
}
#[cfg_attr(feature = "use_attributes", not_hacspec($name))]
fn iter(&self) -> core::slice::Iter<T> {
self.0.iter()
}
#[cfg_attr(feature = "use_attributes", in_hacspec($name))]
fn update_slice<A: SeqTrait<T>>(
mut self,
start_out: usize,
v: &A,
start_in: usize,
len: usize,
) -> Self {
debug_assert!(self.len() >= start_out + len);
debug_assert!(v.len() >= start_in + len);
for i in 0..len {
self[start_out + i] = v[start_in + i];
}
self
}
#[cfg_attr(feature = "use_attributes", in_hacspec($name))]
fn update<A: SeqTrait<T>>(self, start: usize, v: &A) -> Self {
let len = v.len();
self.update_slice(start, v, 0, len)
}
#[cfg_attr(feature = "use_attributes", in_hacspec($name))]
fn update_start<A: SeqTrait<T>>(self, v: &A) -> Self {
let len = v.len();
self.update_slice(0, v, 0, len)
}
}
impl<T: Numeric + Copy> Index<usize> for $name<T> {
type Output = T;
#[cfg_attr(feature = "use_attributes", unsafe_hacspec($name))]
fn index(&self, i: usize) -> &T {
&self.0[i]
}
}
impl<T: Numeric + Copy> IndexMut<usize> for $name<T> {
#[cfg_attr(feature = "use_attributes", unsafe_hacspec($name))]
fn index_mut(&mut self, i: usize) -> &mut T {
&mut self.0[i]
}
}
impl<T: Numeric + Copy> Index<u8> for $name<T> {
type Output = T;
#[cfg_attr(feature = "use_attributes", unsafe_hacspec($name))]
fn index(&self, i: u8) -> &T {
&self.0[i as usize]
}
}
impl<T: Numeric + Copy> IndexMut<u8> for $name<T> {
#[cfg_attr(feature = "use_attributes", not_hacspec($name))]
fn index_mut(&mut self, i: u8) -> &mut T {
&mut self.0[i as usize]
}
}
impl<T: Numeric + Copy> Index<u32> for $name<T> {
type Output = T;
#[cfg_attr(feature = "use_attributes", unsafe_hacspec($name))]
fn index(&self, i: u32) -> &T {
&self.0[i as usize]
}
}
impl<T: Numeric + Copy> IndexMut<u32> for $name<T> {
#[cfg_attr(feature = "use_attributes", not_hacspec($name))]
fn index_mut(&mut self, i: u32) -> &mut T {
&mut self.0[i as usize]
}
}
impl<T: Numeric + Copy> Index<i32> for $name<T> {
type Output = T;
#[cfg_attr(feature = "use_attributes", unsafe_hacspec($name))]
fn index(&self, i: i32) -> &T {
&self.0[i as usize]
}
}
impl<T: Numeric + Copy> IndexMut<i32> for $name<T> {
#[cfg_attr(feature = "use_attributes", not_hacspec($name))]
fn index_mut(&mut self, i: i32) -> &mut T {
&mut self.0[i as usize]
}
}
impl<T: Numeric + Copy> Index<RangeFull> for $name<T> {
type Output = [T];
#[cfg_attr(feature = "use_attributes", unsafe_hacspec($name))]
fn index(&self, r: RangeFull) -> &[T] {
&self.0[r]
}
}
impl<T: Numeric + Copy> $name<T> {
#[cfg_attr(feature = "use_attributes", not_hacspec($name))]
pub fn from_vec(x: Vec<T>) -> $name<T> {
debug_assert_eq!(x.len(), $l);
let mut tmp = [<T>::default(); $l];
for (i, e) in x.iter().enumerate() {
tmp[i] = *e;
}
$name(tmp.clone())
}
#[cfg_attr(feature = "use_attributes", in_hacspec($name))]
pub fn from_seq<U: SeqTrait<T>>(x: &U) -> $name<T> {
debug_assert_eq!(x.len(), $l);
let mut out = $name::new();
for i in 0..x.len() {
out[i] = x[i];
}
out
}
}
impl<T: Numeric + Copy> fmt::Debug for $name<T> {
#[cfg_attr(feature = "use_attributes", not_hacspec($name))]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0[..].iter().collect::<Vec<_>>().fmt(f)
}
}
};
}
#[macro_export]
#[doc(hidden)]
macro_rules! _secret_array {
($name:ident,$l:expr,$t:ty, $tbase:ty) => {
_array_base!($name, $l, $t);
impl fmt::Debug for $name {
#[cfg_attr(feature = "use_attributes", not_hacspec($name))]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0[..]
.iter()
.map(|x| <$t>::declassify(*x))
.collect::<Vec<_>>()
.fmt(f)
}
}
impl $name {
#[cfg_attr(feature = "use_attributes", unsafe_hacspec($name))]
pub fn declassify_eq(&self, other: &Self) -> bool {
self.0[..]
.iter()
.map(|x| <$t>::declassify(*x))
.collect::<Vec<_>>()
== other.0[..]
.iter()
.map(|x| <$t>::declassify(*x))
.collect::<Vec<_>>()
}
}
impl $name {
#[cfg_attr(feature = "use_attributes", unsafe_hacspec)]
pub fn to_be_bytes(&self) -> Seq<U8> {
const FACTOR: usize = core::mem::size_of::<$t>();
let mut out: Seq<U8> = Seq::new($l * FACTOR);
for i in 0..$l {
let tmp: $t = self[i];
let tmp = <$t>::to_be_bytes(&[tmp]);
for j in 0..FACTOR {
out[i * FACTOR + j] = tmp[j];
}
}
out
}
#[cfg_attr(feature = "use_attributes", unsafe_hacspec($name))]
pub fn to_le_bytes(&self) -> Seq<U8> {
const FACTOR: usize = core::mem::size_of::<$t>();
let mut out: Seq<U8> = Seq::new($l * FACTOR);
for i in 0..$l {
let tmp: $t = self[i];
let tmp = <$t>::to_le_bytes(&[tmp]);
for j in 0..FACTOR {
out[i * FACTOR + j] = tmp[j];
}
}
out
}
}
impl $name {
#[cfg_attr(feature = "use_attributes", not_hacspec($name))]
pub fn from_public_slice(v: &[$tbase]) -> $name {
debug_assert!(v.len() == $l);
Self::from_vec(
v[..]
.iter()
.map(|x| <$t>::classify(*x))
.collect::<Vec<$t>>(),
)
}
#[cfg_attr(feature = "use_attributes", not_hacspec($name))]
pub fn to_public_array(&self) -> [$tbase; $l] {
let mut out = [0; $l];
for (x, o) in self.0.iter().zip(out.iter_mut()) {
*o = <$t>::declassify(*x);
}
out
}
#[cfg_attr(feature = "use_attributes", not_hacspec($name))]
pub fn from_public_array(v: [$tbase; $l]) -> $name {
debug_assert!(v.len() == $l);
Self::from_vec(
v[..]
.iter()
.map(|x| <$t>::classify(*x))
.collect::<Vec<$t>>(),
)
}
}
};
}
#[macro_export]
#[doc(hidden)]
macro_rules! _public_array {
($name:ident,$l:expr,$t:ty) => {
_array_base!($name, $l, $t);
impl $name {
#[cfg_attr(feature = "use_attributes", unsafe_hacspec($name))]
pub fn into_le_bytes(self) -> Seq<u8> {
const FACTOR: usize = core::mem::size_of::<$t>();
let mut out: Seq<u8> = Seq::new($l * FACTOR);
for i in 0..$l {
let tmp = <$t>::to_le_bytes(self[i]);
for j in 0..FACTOR {
out[i * FACTOR + j] = tmp[j];
}
}
out
}
}
impl fmt::Debug for $name {
#[cfg_attr(feature = "use_attributes", not_hacspec($name))]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0[..].fmt(f)
}
}
impl PartialEq for $name {
#[cfg_attr(feature = "use_attributes", unsafe_hacspec($name))]
fn eq(&self, other: &Self) -> bool {
self.0[..] == other.0[..]
}
}
};
}
#[macro_export]
#[doc(hidden)]
macro_rules! _implement_secret_u8_array {
($name:ident, $l:expr) => {
_secret_array!($name, $l, U8, u8);
_implement_numeric_unsigned_secret!($name, U8);
impl $name {
#[allow(non_snake_case)]
#[cfg_attr(feature = "use_attributes", unsafe_hacspec($name))]
pub fn to_be_U32s(&self) -> Seq<U32> {
let mut out = Seq::new($l / 4);
for (i, block) in self.0.chunks(4).enumerate() {
debug_assert!(block.len() == 4);
out[i] = U32_from_be_bytes(U32Word::from_native_slice(block));
}
out
}
#[allow(non_snake_case)]
#[cfg_attr(feature = "use_attributes", unsafe_hacspec($name))]
pub fn to_le_U32s(&self) -> Seq<U32> {
let mut out = Seq::new($l / 4);
for (i, block) in self.0.chunks(4).enumerate() {
debug_assert!(block.len() == 4);
out[i] = U32_from_le_bytes(U32Word::from_native_slice(block));
}
out
}
#[allow(non_snake_case)]
#[cfg_attr(feature = "use_attributes", unsafe_hacspec($name))]
pub fn to_be_U64s(&self) -> Seq<U64> {
let mut out = Seq::new($l / 8);
for (i, block) in self.0.chunks(8).enumerate() {
debug_assert!(block.len() == 8);
out[i] = U64_from_be_bytes(U64Word::from_native_slice(block));
}
out
}
#[allow(non_snake_case)]
#[cfg_attr(feature = "use_attributes", unsafe_hacspec($name))]
pub fn to_le_U64s(&self) -> Seq<U64> {
let mut out = Seq::new($l / 8);
for (i, block) in self.0.chunks(8).enumerate() {
debug_assert!(block.len() == 8);
out[i] = U64_from_le_bytes(U64Word::from_native_slice(block));
}
out
}
#[allow(non_snake_case)]
#[cfg_attr(feature = "use_attributes", unsafe_hacspec($name))]
pub fn to_U128s_be(&self) -> Seq<U128> {
let mut out = Seq::new($l / 16);
for (i, block) in self.0.chunks(16).enumerate() {
debug_assert!(block.len() == 16);
out[i] = U128_from_be_bytes(U128Word::from_native_slice(block));
}
out
}
#[allow(non_snake_case)]
#[cfg_attr(feature = "use_attributes", unsafe_hacspec($name))]
pub fn to_U128s_le(&self) -> Seq<U128> {
let mut out = Seq::new($l / 16);
for (i, block) in self.0.chunks(16).enumerate() {
debug_assert!(block.len() == 16);
out[i] = U128_from_le_bytes(U128Word::from_native_slice(block));
}
out
}
#[cfg_attr(feature = "use_attributes", not_hacspec($name))]
pub fn to_hex(&self) -> String {
let strs: Vec<String> = self.0.iter().map(|b| format!("{:02x}", b)).collect();
strs.join("")
}
}
};
}
#[macro_export]
#[doc(hidden)]
macro_rules! _implement_public_u8_array {
($name:ident, $l:expr) => {
_public_array!($name, $l, u8);
_implement_numeric_unsigned_public!($name);
impl $name {
#[cfg_attr(feature = "use_attributes", unsafe_hacspec($name))]
pub fn to_be_u32s(&self) -> Seq<u32> {
let mut out = Seq::new($l / 4);
for (i, block) in self.0.chunks(4).enumerate() {
debug_assert!(block.len() == 4);
out[i] = u32::from_be_bytes(to_array(block));
}
out
}
#[cfg_attr(feature = "use_attributes", unsafe_hacspec($name))]
pub fn to_le_u32s(&self) -> Seq<u32> {
let mut out = Seq::new($l / 4);
for (i, block) in self.0.chunks(4).enumerate() {
debug_assert!(block.len() == 4);
out[i] = u32::from_le_bytes(to_array(block));
}
out
}
#[cfg_attr(feature = "use_attributes", unsafe_hacspec($name))]
pub fn to_be_u64s(&self) -> Seq<u64> {
let mut out = Seq::new($l / 8);
for (i, block) in self.0.chunks(8).enumerate() {
debug_assert!(block.len() == 8);
out[i] = u64::from_be_bytes(to_array(block));
}
out
}
#[cfg_attr(feature = "use_attributes", unsafe_hacspec($name))]
pub fn to_le_u64s(&self) -> Seq<u64> {
let mut out = Seq::new($l / 8);
for (i, block) in self.0.chunks(8).enumerate() {
debug_assert!(block.len() == 8);
out[i] = u64::from_le_bytes(to_array(block));
}
out
}
#[cfg_attr(feature = "use_attributes", unsafe_hacspec($name))]
pub fn to_u128s_be(&self) -> Seq<u128> {
let mut out = Seq::new($l / 16);
for (i, block) in self.0.chunks(16).enumerate() {
debug_assert!(block.len() == 16);
out[i] = u128::from_be_bytes(to_array(block));
}
out
}
#[cfg_attr(feature = "use_attributes", unsafe_hacspec($name))]
pub fn to_u128s_le(&self) -> Seq<u128> {
let mut out = Seq::new($l / 16);
for (i, block) in self.0.chunks(16).enumerate() {
debug_assert!(block.len() == 16);
out[i] = u128::from_le_bytes(to_array(block));
}
out
}
#[cfg_attr(feature = "use_attributes", not_hacspec($name))]
pub fn to_hex(&self) -> String {
let strs: Vec<String> = self.0.iter().map(|b| format!("{:02x}", b)).collect();
strs.join("")
}
}
};
}
#[macro_export]
macro_rules! array {
($name:ident, $l:expr, U8) => {
_implement_secret_u8_array!($name, $l);
};
($name:ident, $l:expr, U8, $idx: ident) => {
_implement_secret_u8_array!($name, $l);
pub type $idx = usize;
};
($name:ident, $l:expr, U16) => {
_secret_array!($name, $l, U16, u16);
_implement_numeric_unsigned_secret!($name, U16);
};
($name:ident, $l:expr, U16, type_for_indexes: $idx: ident) => {
_secret_array!($name, $l, U16, u16);
_implement_numeric_unsigned_secret!($name, U16);
pub type $idx = usize;
};
($name:ident, $l:expr, U32) => {
_secret_array!($name, $l, U32, u32);
_implement_numeric_unsigned_secret!($name, U32);
};
($name:ident, $l:expr, U32, type_for_indexes: $idx: ident) => {
_secret_array!($name, $l, U32, u32);
_implement_numeric_unsigned_secret!($name, U32);
pub type $idx = usize;
};
($name:ident, $l:expr, U64) => {
_secret_array!($name, $l, U64, u64);
_implement_numeric_unsigned_secret!($name, U64);
};
($name:ident, $l:expr, U64, type_for_indexes: $idx: ident) => {
_secret_array!($name, $l, U64, u64);
_implement_numeric_unsigned_secret!($name, U64);
pub type $idx = usize;
};
($name:ident, $l:expr, U128) => {
_secret_array!($name, $l, U128, u128);
_implement_numeric_unsigned_secret!($name, U128);
};
($name:ident, $l:expr, U128, type_for_indexes: $idx: ident) => {
_secret_array!($name, $l, U128, u128);
_implement_numeric_unsigned_secret!($name, U128);
pub type $idx = usize;
};
($name:ident, $l:expr, u8) => {
_implement_public_u8_array!($name, $l);
};
($name:ident, $l:expr, u8, type_for_indexes: $idx: ident) => {
_implement_public_u8_array!($name, $l);
pub type $idx = usize;
};
($name:ident, $l:expr, u16) => {
_public_array!($name, $l, u16);
_implement_numeric_unsigned_public!($name);
};
($name:ident, $l:expr, u16, type_for_indexes: $idx: ident) => {
_public_array!($name, $l, u16);
_implement_numeric_unsigned_public!($name);
pub type $idx = usize;
};
($name:ident, $l:expr, u32) => {
_public_array!($name, $l, u32);
_implement_numeric_unsigned_public!($name);
};
($name:ident, $l:expr, u32, type_for_indexes: $idx: ident) => {
_public_array!($name, $l, u32);
_implement_numeric_unsigned_public!($name);
pub type $idx = usize;
};
($name:ident, $l:expr, u64) => {
_public_array!($name, $l, u64);
_implement_numeric_unsigned_public!($name);
};
($name:ident, $l:expr, u64, type_for_indexes: $idx: ident) => {
_public_array!($name, $l, u64);
_implement_numeric_unsigned_public!($name);
pub type $idx = usize;
};
($name:ident, $l:expr, u128) => {
_public_array!($name, $l, u128);
_implement_numeric_unsigned_public!($name);
};
($name:ident, $l:expr, u128, type_for_indexes: $idx: ident) => {
_public_array!($name, $l, u128);
_implement_numeric_unsigned_public!($name);
pub type $idx = usize;
};
($name:ident, $l:expr, $t:ty) => {
_public_array!($name, $l, $t);
};
($name:ident, $l:expr, $t:ty, type_for_indexes: $idx: ident) => {
_public_array!($name, $l, $t);
pub type $idx = usize;
};
}
#[macro_export]
macro_rules! bytes {
($name:ident, $l:expr) => {
array!($name, $l, U8);
};
}
#[macro_export]
macro_rules! public_bytes {
($name:ident, $l:expr) => {
array!($name, $l, u8);
};
}
#[macro_export]
macro_rules! secret_array {
( $int_type: ident, [ $( $x:expr ),+ ] ) => {
[
$(
$int_type($x)
),+
]
}
}
#[macro_export]
macro_rules! secret_bytes {
([ $( $x:expr ),+ ] ) => {
secret_array!(U8, [$($x),+])
}
}
#[macro_export]
macro_rules! assert_secret_array_eq {
( $a1: expr, $a2: expr, $si: ident) => {
assert_eq!(
$a1.iter().map(|x| $si::declassify(*x)).collect::<Vec<_>>(),
$a2.iter().map(|x| $si::declassify(*x)).collect::<Vec<_>>()
);
};
}
#[macro_export]
macro_rules! assert_bytes_eq {
( $a1: expr, $a2: expr) => {
assert_secret_array_eq!($a1, $a2, U8)
};
}
#[macro_export]
macro_rules! both_arrays {
($public_name:ident, $name:ident, $l:expr, $t:ty, $tbase:ty) => {
_secret_array!($name, $l, $t, $tbase);
_public_array!($public_name, $l, $tbase);
impl $name {
#[cfg_attr(feature = "use_attributes", unsafe_hacspec($name))]
pub fn from_public(v: $public_name) -> $name {
Self::from_vec(
v[..]
.iter()
.map(|x| <$t>::classify(*x))
.collect::<Vec<$t>>(),
)
}
}
impl $public_name {
#[cfg_attr(feature = "use_attributes", unsafe_hacspec($name))]
pub fn from_secret_declassify(v: $name) -> $public_name {
Self::from_vec(
v[..]
.iter()
.map(|x| <$t>::declassify(*x))
.collect::<Vec<$tbase>>(),
)
}
}
};
}
#[macro_export]
macro_rules! both_bytes {
($public_name:ident, $name:ident, $l:expr) => {
both_arrays!($public_name, $name, $l, U8, u8);
};
}