use crate::{
field::{FieldType, GetField, GetFieldMut, GetFieldRawMutFn, IntoField},
path::IsSingleFieldPath,
structural_trait::Structural,
type_level::{
cmp::{Compare, TGreater},
integer::{
IsUnsigned, U0, U1, U10, U11, U12, U13, U14, U15, U16, U17, U18, U19, U2, U20, U21,
U22, U23, U24, U25, U26, U27, U28, U29, U3, U30, U31, U32, U4, U5, U6, U7, U8, U9,
},
},
};
use std_::{marker::PhantomData, mem::ManuallyDrop, ptr};
pub mod array_traits;
pub use self::array_traits::{
Array0, Array1, Array10, Array11, Array12, Array13, Array14, Array15, Array16, Array17,
Array18, Array19, Array2, Array20, Array21, Array22, Array23, Array24, Array25, Array26,
Array27, Array28, Array29, Array3, Array30, Array31, Array32, Array4, Array5, Array6, Array7,
Array8, Array9,
};
pub use self::array_traits::{
Array0Variant, Array10Variant, Array11Variant, Array12Variant, Array13Variant, Array14Variant,
Array15Variant, Array16Variant, Array17Variant, Array18Variant, Array19Variant, Array1Variant,
Array20Variant, Array21Variant, Array22Variant, Array23Variant, Array24Variant, Array25Variant,
Array26Variant, Array27Variant, Array28Variant, Array29Variant, Array2Variant, Array30Variant,
Array31Variant, Array32Variant, Array3Variant, Array4Variant, Array5Variant, Array6Variant,
Array7Variant, Array8Variant, Array9Variant,
};
mod sealed {
pub trait Sealed {}
}
use self::sealed::Sealed;
pub trait ArrayPath: IsSingleFieldPath + Sealed {
const INDEX: usize;
type Index: IsUnsigned;
}
pub trait IsPathForArray<Array>: ArrayPath {
#[doc(hidden)]
const _SEALED_IPFA: SealedIPFA<Self, Array>;
}
#[doc(hidden)]
pub struct SealedIPFA<Path, Array> {
_marker: PhantomData<(Path, Array)>,
}
macro_rules! declare_array_paths {
(
$(
(
$index_name:ident = $index:expr,$index_str:literal,$tnum:ident,$fi_ind:ident,
[$($fi_in_array:ident,)*]
)
)*
) => (
tstr_aliases!{
pub(crate) mod names{
$( $index_name = $index_str ,)*
}
}
use self::names::*;
$(
impl<T> Structural for [T;$index]{}
impl Sealed for $index_name{}
impl ArrayPath for $index_name{
const INDEX:usize=$index;
type Index=$tnum;
}
impl<T,P> IsPathForArray<[T;$index]> for P
where
P:ArrayPath,
$tnum:Compare<P::Index,Output=TGreater>,
{
#[doc(hidden)]
const _SEALED_IPFA:SealedIPFA<P,[T;$index]>=SealedIPFA{_marker:PhantomData};
}
impl<T,P> FieldType<P> for [T;$index]
where
P:IsPathForArray<Self>,
{
type Ty=T;
}
impl<T,P> GetField<P> for [T;$index]
where
P:IsPathForArray<Self>,
{
#[inline(always)]
fn get_field_(&self,_:P)->&Self::Ty{
&self[P::INDEX]
}
}
unsafe impl<T,P> GetFieldMut<P> for [T;$index]
where
P:IsPathForArray<Self>,
{
#[inline(always)]
fn get_field_mut_(&mut self,_:P)->&mut Self::Ty{
&mut self[P::INDEX]
}
#[inline(always)]
unsafe fn get_field_raw_mut(
ptr:*mut (),
_:P,
)->*mut Self::Ty{
let ptr=ptr as *mut T;
ptr.add(P::INDEX)
}
#[inline(always)]
fn get_field_raw_mut_fn(&self)->GetFieldRawMutFn<P,Self::Ty>{
<Self as GetFieldMut<P>>::get_field_raw_mut
}
}
impl<T,P> IntoField<P> for [T;$index]
where
P:IsPathForArray<Self>,
{
#[inline(always)]
fn into_field_(self,_:P)->Self::Ty{
unsafe{
let mut this=ManuallyDrop::new(self);
ptr::drop_in_place(&mut this[..P::INDEX]);
ptr::drop_in_place(&mut this[P::INDEX+1..]);
this.as_mut_ptr().add(P::INDEX).read()
}
}
z_impl_box_into_field_method!{ field_tstr=P }
}
)*
)
}
declare_array_paths! {
(I0=0,"0",U0,FI_0,[
])
(I1=1,"1",U1,FI_1,[
FI_0,
])
(I2=2,"2",U2,FI_2,[
FI_0,FI_1,
])
(I3=3,"3",U3,FI_3,[
FI_0,FI_1,FI_2,
])
(I4=4,"4",U4,FI_4,[
FI_0,FI_1,FI_2,FI_3,
])
(I5=5,"5",U5,FI_5,[
FI_0,FI_1,FI_2,FI_3,FI_4,
])
(I6=6,"6",U6,FI_6,[
FI_0,FI_1,FI_2,FI_3,FI_4,FI_5,
])
(I7=7,"7",U7,FI_7,[
FI_0,FI_1,FI_2,FI_3,FI_4,FI_5,FI_6,
])
(I8=8,"8",U8,FI_8,[
FI_0,FI_1,FI_2,FI_3,FI_4,FI_5,FI_6,FI_7,
])
(I9=9,"9",U9,FI_9,[
FI_0,FI_1,FI_2,FI_3,FI_4,FI_5,FI_6,FI_7,FI_8,
])
(I10=10,"10",U10,FI_10,[
FI_0,FI_1,FI_2,FI_3,FI_4,FI_5,FI_6,FI_7,FI_8,FI_9,
])
(I11=11,"11",U11,FI_11,[
FI_0,FI_1,FI_2,FI_3,FI_4,FI_5,FI_6,FI_7,FI_8,FI_9,
FI_10,
])
(I12=12,"12",U12,FI_12,[
FI_0,FI_1,FI_2,FI_3,FI_4,FI_5,FI_6,FI_7,FI_8,FI_9,
FI_10,FI_11,
])
(I13=13,"13",U13,FI_13,[
FI_0,FI_1,FI_2,FI_3,FI_4,FI_5,FI_6,FI_7,FI_8,FI_9,
FI_10,FI_11,FI_12,
])
(I14=14,"14",U14,FI_14,[
FI_0,FI_1,FI_2,FI_3,FI_4,FI_5,FI_6,FI_7,FI_8,FI_9,
FI_10,FI_11,FI_12,FI_13,
])
(I15=15,"15",U15,FI_15,[
FI_0,FI_1,FI_2,FI_3,FI_4,FI_5,FI_6,FI_7,FI_8,FI_9,
FI_10,FI_11,FI_12,FI_13,FI_14,
])
(I16=16,"16",U16,FI_16,[
FI_0,FI_1,FI_2,FI_3,FI_4,FI_5,FI_6,FI_7,FI_8,FI_9,
FI_10,FI_11,FI_12,FI_13,FI_14,FI_15,
])
(I17=17,"17",U17,FI_17,[
FI_0,FI_1,FI_2,FI_3,FI_4,FI_5,FI_6,FI_7,FI_8,FI_9,
FI_10,FI_11,FI_12,FI_13,FI_14,FI_15,FI_16,
])
(I18=18,"18",U18,FI_18,[
FI_0,FI_1,FI_2,FI_3,FI_4,FI_5,FI_6,FI_7,FI_8,FI_9,
FI_10,FI_11,FI_12,FI_13,FI_14,FI_15,FI_16,FI_17,
])
(I19=19,"19",U19,FI_19,[
FI_0,FI_1,FI_2,FI_3,FI_4,FI_5,FI_6,FI_7,FI_8,FI_9,
FI_10,FI_11,FI_12,FI_13,FI_14,FI_15,FI_16,FI_17,FI_18,
])
(I20=20,"20",U20,FI_20,[
FI_0,FI_1,FI_2,FI_3,FI_4,FI_5,FI_6,FI_7,FI_8,FI_9,
FI_10,FI_11,FI_12,FI_13,FI_14,FI_15,FI_16,FI_17,FI_18,FI_19,
])
(I21=21,"21",U21,FI_21,[
FI_0,FI_1,FI_2,FI_3,FI_4,FI_5,FI_6,FI_7,FI_8,FI_9,
FI_10,FI_11,FI_12,FI_13,FI_14,FI_15,FI_16,FI_17,FI_18,FI_19,
FI_20,
])
(I22=22,"22",U22,FI_22,[
FI_0,FI_1,FI_2,FI_3,FI_4,FI_5,FI_6,FI_7,FI_8,FI_9,
FI_10,FI_11,FI_12,FI_13,FI_14,FI_15,FI_16,FI_17,FI_18,FI_19,
FI_20,FI_21,
])
(I23=23,"23",U23,FI_23,[
FI_0,FI_1,FI_2,FI_3,FI_4,FI_5,FI_6,FI_7,FI_8,FI_9,
FI_10,FI_11,FI_12,FI_13,FI_14,FI_15,FI_16,FI_17,FI_18,FI_19,
FI_20,FI_21,FI_22,
])
(I24=24,"24",U24,FI_24,[
FI_0,FI_1,FI_2,FI_3,FI_4,FI_5,FI_6,FI_7,FI_8,FI_9,
FI_10,FI_11,FI_12,FI_13,FI_14,FI_15,FI_16,FI_17,FI_18,FI_19,
FI_20,FI_21,FI_22,FI_23,
])
(I25=25,"25",U25,FI_25,[
FI_0,FI_1,FI_2,FI_3,FI_4,FI_5,FI_6,FI_7,FI_8,FI_9,
FI_10,FI_11,FI_12,FI_13,FI_14,FI_15,FI_16,FI_17,FI_18,FI_19,
FI_20,FI_21,FI_22,FI_23,FI_24,
])
(I26=26,"26",U26,FI_26,[
FI_0,FI_1,FI_2,FI_3,FI_4,FI_5,FI_6,FI_7,FI_8,FI_9,
FI_10,FI_11,FI_12,FI_13,FI_14,FI_15,FI_16,FI_17,FI_18,FI_19,
FI_20,FI_21,FI_22,FI_23,FI_24,FI_25,
])
(I27=27,"27",U27,FI_27,[
FI_0,FI_1,FI_2,FI_3,FI_4,FI_5,FI_6,FI_7,FI_8,FI_9,
FI_10,FI_11,FI_12,FI_13,FI_14,FI_15,FI_16,FI_17,FI_18,FI_19,
FI_20,FI_21,FI_22,FI_23,FI_24,FI_25,FI_26,
])
(I28=28,"28",U28,FI_28,[
FI_0,FI_1,FI_2,FI_3,FI_4,FI_5,FI_6,FI_7,FI_8,FI_9,
FI_10,FI_11,FI_12,FI_13,FI_14,FI_15,FI_16,FI_17,FI_18,FI_19,
FI_20,FI_21,FI_22,FI_23,FI_24,FI_25,FI_26,FI_27,
])
(I29=29,"29",U29,FI_29,[
FI_0,FI_1,FI_2,FI_3,FI_4,FI_5,FI_6,FI_7,FI_8,FI_9,
FI_10,FI_11,FI_12,FI_13,FI_14,FI_15,FI_16,FI_17,FI_18,FI_19,
FI_20,FI_21,FI_22,FI_23,FI_24,FI_25,FI_26,FI_27,FI_28,
])
(I30=30,"30",U30,FI_30,[
FI_0,FI_1,FI_2,FI_3,FI_4,FI_5,FI_6,FI_7,FI_8,FI_9,
FI_10,FI_11,FI_12,FI_13,FI_14,FI_15,FI_16,FI_17,FI_18,FI_19,
FI_20,FI_21,FI_22,FI_23,FI_24,FI_25,FI_26,FI_27,FI_28,FI_29,
])
(I31=31,"31",U31,FI_31,[
FI_0,FI_1,FI_2,FI_3,FI_4,FI_5,FI_6,FI_7,FI_8,FI_9,
FI_10,FI_11,FI_12,FI_13,FI_14,FI_15,FI_16,FI_17,FI_18,FI_19,
FI_20,FI_21,FI_22,FI_23,FI_24,FI_25,FI_26,FI_27,FI_28,FI_29,
FI_30,
])
(I32=32,"32",U32,FI_32,[
FI_0,FI_1,FI_2,FI_3,FI_4,FI_5,FI_6,FI_7,FI_8,FI_9,
FI_10,FI_11,FI_12,FI_13,FI_14,FI_15,FI_16,FI_17,FI_18,FI_19,
FI_20,FI_21,FI_22,FI_23,FI_24,FI_25,FI_26,FI_27,FI_28,FI_29,
FI_30,FI_31,
])
}
#[cfg(feature = "testing")]
#[allow(dead_code)]
struct Foo0;
#[cfg(test)]
#[allow(clippy::redundant_clone)]
mod tests {
use super::{
Array1, Array15, Array16, Array17, Array23, Array24, Array30, Array31, Array32, Array7,
Array8, Array9, I0, I1, I14, I15, I16, I2, I22, I23, I29, I3, I30, I31, I4, I5, I6, I7, I8,
I9,
};
use crate::StructuralExt;
use std_::convert::TryFrom;
use std_::mem;
#[test]
fn get_field() {
assert_eq!([5].field_(fp!(0)), &5);
{
let arr = [5, 8];
assert_eq!(arr.field_(fp!(0)), &5);
assert_eq!(arr.field_(fp!(1)), &8);
}
{
let arr = [5, 8, 13];
assert_eq!(arr.field_(fp!(0)), &5);
assert_eq!(arr.field_(fp!(1)), &8);
assert_eq!(arr.field_(fp!(2)), &13);
}
}
#[test]
fn get_field_mut() {
assert_eq!([5].field_mut(fp!(0)), &mut 5);
{
let mut arr = [5, 8];
assert_eq!(arr.field_mut(fp!(0)), &mut 5);
assert_eq!(arr.field_mut(fp!(1)), &mut 8);
}
{
let mut arr = [5, 8, 13];
assert_eq!(arr.field_mut(fp!(0)), &mut 5);
assert_eq!(arr.field_mut(fp!(1)), &mut 8);
assert_eq!(arr.field_mut(fp!(2)), &mut 13);
}
assert_eq!([5].field_mut(fp!(0)), &mut 5);
assert_eq!([5, 8].fields_mut(fp!(0, 1)), (&mut 5, &mut 8));
assert_eq!(
[5, 8, 13].fields_mut(fp!(0, 1, 2)),
(&mut 5, &mut 8, &mut 13)
);
{
let mut array = [5, 8, 13];
let (e0, e1, e2) = array.fields_mut(fp!(0, 1, 2));
mem::swap(e0, e1);
mem::swap(e0, e2);
mem::swap(e1, e2);
assert_eq!(array, [13, 8, 5]);
}
}
#[test]
fn into_field() {
assert_eq!([5].into_field(fp!(0)), 5);
{
let arr = [5, 8];
assert_eq!(arr.clone().into_field(fp!(0)), 5);
assert_eq!(arr.clone().into_field(fp!(1)), 8);
}
{
let arr = [5, 8, 13];
assert_eq!(arr.clone().into_field(fp!(0)), 5);
assert_eq!(arr.clone().into_field(fp!(1)), 8);
assert_eq!(arr.clone().into_field(fp!(2)), 13);
}
{
use crate::test_utils::DecOnDrop;
use std_::cell::Cell;
let counter = Cell::new(0);
let cnt = DecOnDrop::new(&counter);
[cnt.clone()].into_field(fp!(0));
assert_eq!(counter.get(), 1);
{
let arr = [cnt.clone(), cnt.clone()];
assert_eq!(counter.get(), 3);
arr.clone().into_field(fp!(0));
arr.clone().into_field(fp!(1));
}
assert_eq!(counter.get(), 1);
{
let arr = [cnt.clone(), cnt.clone(), cnt.clone()];
assert_eq!(counter.get(), 4);
arr.clone().into_field(fp!(0));
arr.clone().into_field(fp!(1));
arr.clone().into_field(fp!(2));
}
assert_eq!(counter.get(), 1);
drop(cnt);
assert_eq!(counter.get(), 0);
}
}
#[test]
#[allow(clippy::cognitive_complexity)]
fn structural_aliases() {
let mut array = [0i32; 32];
(0..=31).for_each(|x| array[x as usize] = 100 + x);
macro_rules! structural_alias_test {
(
$size:literal,$trait_:ident,[$(($field:ident,$index:literal)),* $(,)* ]
) => ({
fn constraint<T>(_:&impl $trait_<T>){}
let arr=<&[i32;$size]>::try_from(&array[0..$size]).unwrap().clone();
constraint(&arr);
$(
assert_eq!( arr.field_(<$field>::NEW), &array[$index] );
)*
})
}
structural_alias_test!(1, Array1, [(I0, 0),]);
structural_alias_test!(
7,
Array7,
[
(I0, 0),
(I1, 1),
(I2, 2),
(I3, 3),
(I4, 4),
(I5, 5),
(I6, 6),
]
);
structural_alias_test!(8, Array8, [(I0, 0), (I6, 6), (I7, 7),]);
structural_alias_test!(9, Array9, [(I0, 0), (I7, 7), (I8, 8),]);
structural_alias_test!(
15,
Array15,
[(I0, 0), (I7, 7), (I8, 8), (I9, 9), (I14, 14),]
);
structural_alias_test!(
16,
Array16,
[(I0, 0), (I7, 7), (I8, 8), (I14, 14), (I15, 15),]
);
structural_alias_test!(
17,
Array17,
[(I0, 0), (I7, 7), (I8, 8), (I14, 14), (I15, 15), (I16, 16),]
);
structural_alias_test!(
23,
Array23,
[
(I0, 0),
(I7, 7),
(I8, 8),
(I14, 14),
(I15, 15),
(I16, 16),
(I22, 22),
]
);
structural_alias_test!(
24,
Array24,
[
(I0, 0),
(I7, 7),
(I8, 8),
(I14, 14),
(I15, 15),
(I16, 16),
(I22, 22),
(I23, 23),
]
);
structural_alias_test!(
30,
Array30,
[
(I0, 0),
(I7, 7),
(I8, 8),
(I14, 14),
(I15, 15),
(I16, 16),
(I22, 22),
(I23, 23),
(I29, 29),
]
);
structural_alias_test!(
31,
Array31,
[
(I0, 0),
(I7, 7),
(I8, 8),
(I14, 14),
(I15, 15),
(I16, 16),
(I22, 22),
(I23, 23),
(I29, 29),
(I30, 30),
]
);
structural_alias_test!(
32,
Array32,
[
(I0, 0),
(I7, 7),
(I8, 8),
(I14, 14),
(I15, 15),
(I16, 16),
(I22, 22),
(I23, 23),
(I29, 29),
(I30, 30),
(I31, 31),
]
);
}
}