#![cfg_attr( feature = "unstable", feature( fn_traits, generator_trait, generators, proc_macro_hygiene, stmt_expr_attributes, trusted_len, unboxed_closures, ))] use enumx::export::*; def_impls! { #[derive( Exchange )] enum Enum![1..=3]; } #[test] fn syntax() { fn _foo( i: i32 ) -> Enum!( String, &'static str ) { if i >= 0 { String::from("positive").exchange_into() } else { "negative".exchange_into() } } #[enumx] fn _bar( i: i32 ) -> Enum!( String, usize, &'static str ) { #[ty_pat] match _foo(i) { String(s) => if s.len() % 2 == 0 { s.len().exchange_into() } else { s.exchange_into() }, TyPat::<&'static str>(s) => s.exchange_into(), } } #[enumx] fn _bar_v2( i: i32 ) -> Enum!( String, usize, &'static str ) { #[ty_pat(gen_variants)] match _foo(i) { String(s) => if s.len() % 2 == 0 { s.len().exchange_into() } else { s.exchange_into() }, } } #[enumx] fn _bar_v3( i: i32 ) -> Enum!( String, usize, &'static str ) { #[ty_pat(gen &'static str)] match _foo(i) { String(s) => if s.len() % 2 == 0 { s.len().exchange_into() } else { s.exchange_into() }, } } #[enumx] fn _baz( i: i32 ) -> Enum!( String, &'static str ) { #[ty_pat(gen_variants)] match _bar(i) { usize(v) => v.to_string().exchange_into(), } } #[cfg( feature = "unstable" )] let _bar = #[enumx] |i: i32| -> Enum!( String, usize, &'static str ) { #[ty_pat] match _foo(i) { String(s) => if s.len() % 2 == 0 { s.len().into_enum() } else { s.into_enum() }, TyPat::<&'static str>(s) => s.into_enum(), } }; #[cfg( feature = "unstable" )] #[enumx] let _bar_v2 = |i: i32| -> Enum!( String, usize, &'static str ) { #[ty_pat(gen_variants)] match _foo(i) { String(s) => if s.len() % 2 == 0 { s.len().into_enum() } else { s.into_enum() }, } }; } #[test] fn sum_syntax() { #[sum] fn _if( cond: bool ) -> impl Clone { if cond { #[variant] 1_i32 } else { #[variant] 0_u32 } } #[cfg( feature = "unstable" )] #[sum] fn _fn( cond: bool ) -> impl Fn()->i32 { if cond { #[variant] || 1 } else { #[variant] || 0 } } struct ESI0; impl Iterator for ESI0 { type Item = (); fn next( &mut self ) -> Option<()> { None } fn size_hint( &self ) -> (usize, Option) { (0,Some(0)) } } impl ExactSizeIterator for ESI0 {} struct ESI1; impl Iterator for ESI1 { type Item = (); fn next( &mut self ) -> Option<()> { None } fn size_hint( &self ) -> (usize, Option) { (0,Some(0)) } } impl ExactSizeIterator for ESI1 {} #[sum] fn _exact_size_iterator( cond: bool ) -> impl ExactSizeIterator { if cond { #[variant] ESI0 } else { #[variant] ESI1 } } #[sum( ok => impl Clone )] #[sum( err => impl Clone )] fn _sum_okeys_and_errors( branch: i32 ) -> Result { match branch % 4 { 0 => Ok( #[variant( ok => _ )] branch ), 1 => Ok( #[variant( ok => _ )] () ), 2 => Err( #[variant( err => _ )] branch ), 3 => Err( #[variant( err => _ )] () ), _ => unreachable!(), } } #[sum_err] #[sum( impl Clone )] fn _sum_err( branch: i32 ) -> Result<(), impl Clone> { match branch % 3 { 0 => Ok(()), 1 => Ok( Err( 0 )? ), 2 => Ok( Err( "lorum" )? ), _ => unreachable!(), } } } #[test] fn impl_for_predefined() { impl_trait!{ _impl!(T) AsRef _for!( Enum![1..=3] )} impl_trait!{ _impl!(T) AsMut _for!( Enum![1..=3] )} impl_trait!{ DoubleEndedIterator _for!( Enum![1..=3] )} impl_trait!{ ExactSizeIterator _for!( Enum![1..=3] )} impl_trait!{ _impl!(A) Extend _for!( Enum![1..=3] )} #[cfg( feature = "unstable" )] impl_trait!{ _impl!(Args) Fn _for!( Enum![1..=3] )} impl_trait!{ Iterator _for!( Enum![1..=3] )} impl_trait!{ std::error::Error _for!( Enum![1..=3] )} impl_trait!{ std::fmt::Debug _for!( Enum![1..=3] )} impl_trait!{ std::fmt::Display _for!( Enum![1..=3] )} impl_trait!{ std::iter::FusedIterator _for!( Enum![1..=3] )} #[cfg( feature = "unstable" )] impl_trait!{ std::iter::TrustedLen _for!( Enum![1..=3] )} impl_trait!{ std::io::BufRead _for!( Enum![1..=3] )} impl_trait!{ std::io::Read _for!( Enum![1..=3] )} impl_trait!{ std::io::Seek _for!( Enum![1..=3] )} impl_trait!{ std::io::Write _for!( Enum![1..=3] )} impl_trait!{ std::ops::Deref _for!( Enum![1..=3] )} impl_trait!{ std::ops::DerefMut _for!( Enum![1..=3] )} #[cfg( feature = "unstable" )] impl_trait!{ _impl!(R) std::ops::Generator _for!( Enum![1..=3] )} impl_trait!{ _impl!(Idx) std::ops::Index _for!( Enum![1..=3] )} impl_trait!{ _impl!(Idx) std::ops::IndexMut _for!( Enum![1..=3] )} impl_trait!{ _impl!(T) std::ops::RangeBounds _for!( Enum![1..=3] )} } #[test] #[allow( dead_code )] fn single_impl() { enum Value { Code( i32 ), Text( String ), } impl_trait! { std::fmt::Debug _for!( _def!{ enum Value { Code( i32 ), Text( String ), }} )} } #[test] #[allow( dead_code )] fn single_impl_with_generics() { enum Value { Code( i32 ), Text( &'static str ), Other( Other ), } impl_trait! { _impl!(Other) std::fmt::Debug _for!( _def!{ enum Value { Code( i32 ), Text( &'static str ), Other( Other ), }} ) } } #[test] #[allow( dead_code )] fn impl_trait_for_def() { enum Value { Code( i32 ), Text( &'static str ), Other( Other ), } impl_trait! { _impl!(Other) std::fmt::Debug _for!( _def!{ enum Value { Code( i32 ), Text( &'static str ), Other( Other ), }} ) } }