// This is disabled because Rust keeps rebuilding the entire crate every time I modify // a module in the tests folder. pub mod disabled_enabled_iter; // use self::disabled_enabled_iter::DisabledEnabled; #[allow(unused_imports)] use core_extensions::{Void,SelfOps}; use std::io::Write as ioWrite; use std::{iter,slice,env, fs, io, path}; #[derive(Debug,Copy,Clone,PartialEq,Eq,Hash)] pub enum VariantKind{ Braced, Tupled, Unit, } #[derive(Debug,Copy,Clone,PartialEq,Eq)] pub enum Privacy{ Public, PrivateField, } #[derive(Debug,Copy,Clone,PartialEq,Eq,Hash)] pub enum StructOrEnum{ Struct, Enum, } bitflags! { pub struct EnabledImpl: u32 { const EMPTY=0; const CONST_EQ =0b0000_0001; const CONST_ORD=0b0000_0010; const CONST_EQ_ORD=0b0000_0011; } } impl Default for EnabledImpl{ fn default()->Self{ EnabledImpl::empty() } } #[derive(Debug,Copy,Clone,PartialEq,Eq)] pub enum ConstOrRunt{ Const, Runt, } fn get_typename( s_or_e:StructOrEnum, var_kind:VariantKind, privacy:Privacy, c_or_r:ConstOrRunt, impls:EnabledImpl, )->String { let mut name=String::new(); if let (Privacy::PrivateField,ConstOrRunt::Const)=(privacy,c_or_r) { name.push_str("New"); } if c_or_r==ConstOrRunt::Const && s_or_e==StructOrEnum::Struct { name.push_str("Const"); } name.push_str(match s_or_e { StructOrEnum::Struct=>"Struct_", StructOrEnum::Enum=>"Enum_", }); name.push_str(match var_kind { VariantKind::Unit =>"Unit_", VariantKind::Braced=>"Braced_", VariantKind::Tupled=>"Tupled_", }); if impls.contains(EnabledImpl::CONST_EQ ) { name.push_str("Eq_"); } if impls.contains(EnabledImpl::CONST_ORD) { name.push_str("Ord_"); } match privacy { Privacy::PrivateField=>name.push_str("Priv"), Privacy::Public=>{}, } name } pub type ItemType=(StructOrEnum,VariantKind,Privacy,EnabledImpl); pub static TEST_CASES:&'static [ItemType]={ use self::StructOrEnum as SOE; use self::EnabledImpl as EI; use self::VariantKind as VK; &[ (SOE::Struct,VK::Braced,Privacy::Public ,EI::EMPTY ), (SOE::Struct,VK::Braced,Privacy::Public ,EI::CONST_EQ ), (SOE::Struct,VK::Braced,Privacy::Public ,EI::CONST_ORD ), (SOE::Struct,VK::Braced,Privacy::Public ,EI::CONST_EQ_ORD), (SOE::Enum ,VK::Braced,Privacy::Public ,EI::EMPTY ), (SOE::Enum ,VK::Braced,Privacy::Public ,EI::CONST_EQ ), (SOE::Enum ,VK::Braced,Privacy::Public ,EI::CONST_ORD ), (SOE::Enum ,VK::Braced,Privacy::Public ,EI::CONST_EQ_ORD), (SOE::Struct,VK::Braced,Privacy::PrivateField,EI::CONST_EQ ), (SOE::Struct,VK::Tupled,Privacy::PrivateField,EI::CONST_EQ_ORD), (SOE::Struct,VK::Tupled,Privacy::Public ,EI::CONST_EQ_ORD), (SOE::Enum ,VK::Tupled,Privacy::Public ,EI::CONST_EQ_ORD), (SOE::Struct,VK::Unit ,Privacy::Public ,EI::CONST_EQ_ORD), (SOE::Enum ,VK::Unit ,Privacy::Public ,EI::CONST_EQ_ORD), ] }; fn type_impls_permutations()->iter::Cloned>{ TEST_CASES.iter().cloned() } fn impls_test(mut w:W)->io::Result<()> { writeln!(w,"{}"," type TestEq=( AssertEq,Val> , AssertEq,Val> , ); type TestOrd=( AssertEq,Val> , AssertEq,TypeFn> , ); type TestSetField= TestSetFieldHelper< SetField, Field, Val, NewThis, >; type TestSetFieldHelper=( AssertEq, AssertEq,Val>, ); type TestGetFR= AssertEq,Val>; type TestGetF=( AssertEq,Val>, AssertEq<>::Output,ConstWrapper>, ); ")?; for (soe,var_kind,privacy,impls) in type_impls_permutations() { let name=get_typename(soe,var_kind,privacy,ConstOrRunt::Const,impls); let deriving_type=get_typename(soe,var_kind,privacy,ConstOrRunt::Runt,impls); let consttype=format!("{}Type",deriving_type); let pre_priv=match privacy { Privacy::PrivateField=>"priv_", Privacy::Public=>"", }; let co =if var_kind==VariantKind::Unit {"//"}else{""}; let col=if var_kind==VariantKind::Unit {"/*"}else{""}; let cor=if var_kind==VariantKind::Unit {"*/"}else{""}; writeln!(w," #[allow(non_snake_case)] #[test] fn test_{name}(){{ use self::type_level_{deriving}::*; ",name=name,deriving=deriving_type)?; match soe { StructOrEnum::Enum=>{ writeln!(w," type Open0=Open {col} {cor}; type Open1=Open {col} {cor}; type Open2=Open {col} {cor}; ", col=col,cor=cor )?; } StructOrEnum::Struct=>{ writeln!(w," type Val0={name} {col} {cor}; type Val1={name} {col} {cor}; type Val2={name} {col} {cor}; type Val3={name} {col} {cor}; ", col=col,cor=cor , name=name)?; } } match (impls.contains(EnabledImpl::CONST_EQ ),var_kind,soe) { (false,_,_)=>{}, (true,VariantKind::Unit,StructOrEnum::Struct)=>{ writeln!(w,"let _:TestEq<{name},{name},True>;",name=name)?; } (true ,_,StructOrEnum::Struct)=>{ writeln!(w," let _:TestEq; let _:TestEq; let _:TestEq; let _:TestEq; let _:TestEq; let _:TestEq; let _:TestEq; let _:TestEq; let _:TestEq; let _:TestEq; ")?; }, (true ,_,StructOrEnum::Enum )=>{ writeln!(w," let _:TestEq; let _:TestEq; let _:TestEq; let _:TestEq; let _:TestEq; let _:TestEq; let _:TestEq; let _:TestEq; let _:TestEq; let _:TestEq; let _:TestEq; {co}let _:TestEq; {co}let _:TestEq; {co}let _:TestEq; ", co=co )?; }, } match (impls.contains(EnabledImpl::CONST_ORD ),var_kind,soe) { (false,_,_)=>{}, (true,VariantKind::Unit,StructOrEnum::Struct)=>{ writeln!(w,"let _:TestOrd<{name},{name},Equal_>;",name=name)?; } (true,_,StructOrEnum::Struct)=>{ writeln!(w," let _:TestOrd; let _:TestOrd; let _:TestOrd; let _:TestOrd; let _:TestOrd; let _:TestOrd; let _:TestOrd; let _:TestOrd; let _:TestOrd; let _:TestOrd; ")?; }, (true,_,StructOrEnum::Enum)=>{ writeln!(w," let _:TestOrd; let _:TestOrd; let _:TestOrd; let _:TestOrd; let _:TestOrd; let _:TestOrd; let _:TestOrd; let _:TestOrd; let _:TestOrd; let _:TestOrd; let _:TestOrd; {co}let _:TestOrd; {co}let _:TestOrd; {co}let _:TestOrd; ", co=co )?; }, } match soe { StructOrEnum::Struct=>{ let tuple_acc_1=match privacy { Privacy::PrivateField=>"field_1", Privacy::Public=>"U1", }; let (const_fields,runt_fields,assoc_fields)=match var_kind { VariantKind::Unit |VariantKind::Tupled=>(("U0",tuple_acc_1),("0","1"),("field_0","field_1")), VariantKind::Braced=>("x","y").piped(|x| (x,x,x) ), }; writeln!(w," let _:AssertEq< GetDiscrOf, Discriminant >; {co}let _:AssertEq,variants::{deriving}_Variant>; {co}let _:TestSetField>; {co}let _:TestSetField>; {co}let _:AssertEq,{name}>; {co} {co}let _:TestGetF; {co}let _:TestGetF; {co} {co}let _:TestGetFR,bool>; {co}let _:TestGetFR,Option>; let _:AssertEq< <{deriving} {col}{cor} as IntoConstType_>::ToConst , {consttype} >; assert_eq_into!( {name} {col} > {cor}, {deriving} {col} {{ {rx}:false,{ry}:Some(0u32) }} {cor} ); assert_eq_into!( {name} {col} > {cor}, {deriving} {col} {{ {rx}:true,{ry}:Some(0u32) }} {cor} ); assert_eq_into!( {name} {col} {cor}, {deriving} {col} {{ {rx}:true,{ry}:None::<()> }} {cor} ); let _:AssertEq,{consttype} >; let _:AssertEq,{consttype} >; let _:AssertEq,{consttype} >; let _:AssertEq,{consttype} >; {co}let _:AssertEq<::{at_x} , U0>; {co}let _:AssertEq<::{ppriv}{at_y} , U10>; {co} {co}let _:AssertEq<>::rt_{at_x} , U0>; {co}let _:AssertEq< {co} >::rt_{ppriv}{at_y} , {co} U10 {co}>; let _:AssertEq,tlist![{col} U0,U0 {cor}]>; let _:AssertEq,tlist![{col} U0,U10 {cor}]>; let _:AssertEq,tlist![{col} U10,U0 {cor}]>; let _:AssertEq,tlist![{col} U10,U10 {cor}]>; let _:AssertEq< <{deriving}_Uninit as InitializationValues>::Uninitialized, {name} {col} < UninitField , UninitField > {cor} >; let _:AssertEq< <{deriving}_Uninit as InitializationValues>::Initialized, {name} {col} < IsInitField , IsInitField > {cor} >; ", col=col,cor=cor,co=co, x=const_fields.0, y=const_fields.1, at_x=assoc_fields.0, at_y=assoc_fields.1, rx=runt_fields.0, ry=runt_fields.1, name=name, deriving=deriving_type, consttype=consttype, ppriv=pre_priv, )?; } StructOrEnum::Enum=>{ writeln!(w," let _:AssertEq< GetDiscrOf, Discriminant >; let _:AssertEq< GetDiscrOf, Discriminant >; let _:AssertEq< GetDiscrOf, Discriminant >; let _:AssertEq< GetDiscrOf, Discriminant >; let _:AssertEq,variants::HalfOpen_Variant>; let _:AssertEq,variants::Open_Variant>; let _:AssertEq,variants::Open_Variant>; let _:AssertEq,variants::Closed_Variant>; {co}let _:TestSetField>; {co}let _:AssertEq,Open>; {co}let _:TestSetField< {co} Open0, {co} fields::{accessor}, {co} U3, {co} Construct {co}>; {co} {co}let _:TestGetF; {co} {co}let _:TestGetFR; let _:AssertEq<<{deriving} as IntoConstType_>::ToConst , {consttype} >; assert_eq_into!( HalfOpen, {deriving}::HalfOpen ); assert_eq_into!( Open0, {deriving}::Open {co} {{ {remaining}:0}} ); assert_eq_into!( Open1, {deriving}::Open {co} {{ {remaining}:10}} ); assert_eq_into!( Open2, {deriving}::Open {co} {{ {remaining}:100}} ); assert_eq_into!( Closed, {deriving}::Closed ); let _:AssertEq,{consttype} >; let _:AssertEq,{consttype} >; let _:AssertEq,{consttype} >; let _:AssertEq,{consttype} >; let _:AssertEq,{consttype} >; {co}let _:AssertEq<::{assoc_ty} , U0>; {co}let _:AssertEq<::{assoc_ty} , U10>; {co}let _:AssertEq<::{assoc_ty} , U100>; fn assertions() where Open0:OpenTrait+OpenWithRuntime, Open1:OpenTrait+OpenWithRuntime, Open2:OpenTrait+OpenWithRuntime, HalfOpen:HalfOpenTrait+HalfOpenWithRuntime, Closed:ClosedTrait+ClosedWithRuntime, {{}} assertions(); {co}let _:AssertEq<::rt_{assoc_ty} , U0>; {co}let _:AssertEq<::rt_{assoc_ty} , U10>; {co}let _:AssertEq<::rt_{assoc_ty} , U100>; let _:AssertEq,tlist![]>; let _:AssertEq,tlist![{col}U0 {cor}]>; let _:AssertEq,tlist![{col}U10 {cor}]>; let _:AssertEq,tlist![{col}U100{cor}]>; let _:AssertEq,tlist![]>; let _:AssertEq< ::Initialized, HalfOpen >; let _:AssertEq< ::Uninitialized, HalfOpen >; let _:AssertEq< ::Uninitialized, Open {col} > {cor} >; let _:AssertEq< ::Initialized, Open {col} > {cor} >; let _:AssertEq< ::Initialized, Closed >; let _:AssertEq< ::Uninitialized, Closed >; ", remaining=match var_kind { VariantKind::Braced=>"remaining", VariantKind::Tupled=>"0", VariantKind::Unit=>"", }, accessor=match var_kind { VariantKind::Braced=>"remaining", VariantKind::Tupled=>"U0", VariantKind::Unit=>"", }, assoc_ty=match var_kind { VariantKind::Braced=>"remaining", VariantKind::Tupled=>"field_0", VariantKind::Unit=>"", }, co=co ,col=col,cor=cor, deriving=deriving_type, consttype=consttype, )?; } }; write!(w,"}}\n\n")?; } Ok(()) } fn type_decls(mut w:W)->io::Result<()> { for (soe,var_kind,privacy,impls) in type_impls_permutations() { let deriving_type=get_typename(soe,var_kind,privacy,ConstOrRunt::Runt,impls); #[allow(unused_variables)] let co =if var_kind==VariantKind::Unit {"//"}else{""}; let col=if var_kind==VariantKind::Unit {"/*"}else{""}; let cor=if var_kind==VariantKind::Unit {"*/"}else{""}; write!(w," #[derive(TypeLevel)] //#[typelevel(print_derive)] #[typelevel(derive_str)] #[typelevel(derive( ")?; if impls.contains(EnabledImpl::CONST_EQ ) { write!(w,"ConstEq,")?; } if impls.contains(EnabledImpl::CONST_ORD) { write!(w,"ConstOrd,")?; } writeln!(w,"))]")?; match soe { StructOrEnum::Struct=>{ let priv_=match privacy { Privacy::Public=>"pub", Privacy::PrivateField=>"", }; match var_kind { VariantKind::Braced=> writeln!(w," #[derive(Debug,PartialEq,Eq)] pub struct {deriving} {{ pub x:bool, {priv_} y:Option, }} type Alias{deriving}={deriving}<()>; ", priv_=priv_, deriving=deriving_type )?, VariantKind::Tupled=> writeln!(w," #[derive(Debug,PartialEq,Eq)] pub struct {deriving} ( pub bool,{priv_} Option ); type Alias{deriving}={deriving}<()>; ", priv_=priv_, deriving=deriving_type )?, VariantKind::Unit=> writeln!(w," #[derive(Debug,PartialEq,Eq)] pub struct {deriving}; type Alias{deriving}={deriving}; ", deriving=deriving_type )?, } if privacy==Privacy::PrivateField { let type_alias= get_typename(soe,var_kind,Privacy::PrivateField,ConstOrRunt::Const,impls); let tuple_acc_1=match privacy { Privacy::PrivateField=>"field_1", Privacy::Public=>"U1", }; let (x,y)=match var_kind { VariantKind::Braced=>("x","y"), VariantKind::Unit |VariantKind::Tupled=>("U0",tuple_acc_1), }; write!(w,"\ pub type {alias}{col}{cor}=Construct<\n\ self::type_level_{deriving}::{deriving}_Uninit , ({col} (self::type_level_{deriving}::fields::{x},X),\n\ (self::type_level_{deriving}::fields::{y},Y),\n {cor} ) >;\n ", col=col,cor=cor, alias=type_alias, x=x,y=y, deriving=deriving_type, )?; writeln!(w,"")?; } } StructOrEnum::Enum=>{ writeln!(w," #[derive(Debug,PartialEq,Eq)] pub enum {deriving} {{ HalfOpen, {open}, Closed, }} type Alias{deriving}={deriving}; impl {deriving} {{ fn test_variants_constructible() {{ use self::type_level_{deriving}::*; let _:HalfOpen=HalfOpen; let _:Open{col}{cor}={const_open}; let _:Closed=Closed; }} }} ", col=col,cor=cor, open=match var_kind { VariantKind::Braced=>"Open{remaining:u32}", VariantKind::Tupled=>"Open(u32)", VariantKind::Unit=>"Open", }, deriving=deriving_type, const_open=match var_kind { VariantKind::Braced=>"Open{remaining:U0::CW}", VariantKind::Tupled=>"Open(U0::CW)", VariantKind::Unit=>"Open", } )?; } }; } Ok(()) } fn imports(mut w:W)->io::Result<()> { write!(w," #[allow(dead_code)] mod tests{{ use std::ops::Index; use type_level_values::prelude::*; use type_level_values::ops::*; use type_level_values::collection_ops::{{Reverse}}; use type_level_values::std_types::cmp_ordering::{{Less_,Equal_,ReverseOrd}}; use type_level_values::discriminant::{{GetDiscrOf,GetVariantOf,Discriminant}}; use type_level_values::field_traits::{{GetField,SetField,GetFieldRuntime}}; use type_level_values::initialization::{{ InitializationValues, IsInitField, UninitField, }}; // use derive_type_level_lib::parse_syn::parse_syn_use; macro_rules! assert_eq_into{{ ( $tylevel:ty , $runt:expr ) => ({{ let runtime_val=$runt; assert_eq!( <$tylevel as IntoRuntime<_>>::to_runtime() , runtime_val ); #[cfg(rust_1_22)] assert_eq!( <$tylevel as IntoConstant<_>>::VALUE , runtime_val ); }}) }} ")?; Ok(()) } pub fn build_tests()->io::Result<()>{ let out_dir = env::var("OUT_DIR").unwrap(); let test_path = path::Path::new(&out_dir).join("struct_enum_tests.rs"); let test_file = fs::File::create(&test_path)?; let mut test_file = io::BufWriter::new(test_file); imports(&mut test_file)?; type_decls(&mut test_file)?; impls_test(&mut test_file)?; write!(test_file,"\n}}")?; Ok(()) }