use crate::{
field_traits::{GetField,GetFieldMut,GetFieldMutRefFn,IntoField},
structural_trait::{FieldInfo,Structural,StructuralDyn},
type_level::{
cmp::{Compare_,TGreater},
integer::*,
IsFieldPath,
},
};
use std_::{
marker::PhantomData,
mem::ManuallyDrop,
ptr,
};
pub mod array_traits;
pub use self::array_traits::{
Array0,Array1,Array2,Array3,Array4,Array5,Array6,Array7,
Array8,Array9,Array10,Array11,Array12,Array13,Array14,Array15,
Array16,Array17,Array18,Array19,Array20,Array21,Array22,Array23,
Array24,Array25,Array26,Array27,Array28,Array29,Array30,Array31,
Array32,
};
mod sealed{
pub trait Sealed{}
}
use self::sealed::Sealed;
pub trait ArrayPath:IsFieldPath+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,$tnum:ident,$fi_ind:ident,
[$($fi_in_array:ident,)*]
)
)*
) => (
field_path_aliases_module!{
pub(crate) mod names{
$( $index_name = $index ,)*
}
}
use self::names::*;
const FIELD_INFOS:&'static [FieldInfo;33]=&[
$( $fi_ind, )*
];
$(
const $fi_ind:FieldInfo=FieldInfo::not_renamed(stringify!($index));
impl<T> Structural for [T;$index]{
const FIELDS:&'static[FieldInfo]=&[
$( $fi_in_array, )*
];
}
impl<T> StructuralDyn for [T;$index]{
fn fields_info(&self)->&'static[FieldInfo]{
&FIELD_INFOS[..$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> GetField<P> for [T;$index]
where
P:IsPathForArray<Self>,
{
type Ty=T;
#[inline(always)]
fn get_field_(&self)->&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)->&mut Self::Ty{
&mut self[P::INDEX]
}
#[inline(always)]
unsafe fn get_field_raw_mut(ptr:*mut (),_:PhantomData<P>)->*mut Self::Ty{
(ptr as *mut T).add(P::INDEX)
}
#[inline(always)]
fn get_field_raw_mut_func(&self)->GetFieldMutRefFn<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)->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!{ P }
}
)*
)
}
declare_array_paths!{
(I0=0,U0,FI_0,[
])
(I1=1,U1,FI_1,[
FI_0,
])
(I2=2,U2,FI_2,[
FI_0,FI_1,
])
(I3=3,U3,FI_3,[
FI_0,FI_1,FI_2,
])
(I4=4,U4,FI_4,[
FI_0,FI_1,FI_2,FI_3,
])
(I5=5,U5,FI_5,[
FI_0,FI_1,FI_2,FI_3,FI_4,
])
(I6=6,U6,FI_6,[
FI_0,FI_1,FI_2,FI_3,FI_4,FI_5,
])
(I7=7,U7,FI_7,[
FI_0,FI_1,FI_2,FI_3,FI_4,FI_5,FI_6,
])
(I8=8,U8,FI_8,[
FI_0,FI_1,FI_2,FI_3,FI_4,FI_5,FI_6,FI_7,
])
(I9=9,U9,FI_9,[
FI_0,FI_1,FI_2,FI_3,FI_4,FI_5,FI_6,FI_7,FI_8,
])
(I10=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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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)]
mod tests{
use super::*;
use crate::GetFieldExt;
use std_::mem;
use std_::convert::TryFrom;
#[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 std_::cell::Cell;
use crate::test_utils::DecOnDrop;
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]
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), &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),
]);
}
}