pub struct AA;
pub struct AN;
pub struct NA;
pub struct NN;
pub struct VA;
pub struct VN;
pub struct FV;
pub struct XF;
pub trait FromVariant<Variant,Index> {
fn from_variant( variant: Variant ) -> Self;
}
pub trait IntoEnum<Enum,Index> {
fn into_enum( self ) -> Enum;
}
impl<Enum,Variant,Index> IntoEnum<Enum,Index> for Variant
where Enum: FromVariant<Variant,Index>
{
fn into_enum( self ) -> Enum {
FromVariant::<Variant,Index>::from_variant( self )
}
}
pub trait ExchangeFrom<Src,Indices> {
fn exchange_from( src: Src ) -> Self;
}
impl<Src,Dest,Proto,Indices> ExchangeFrom<Src,(Indices,NA)> for Dest
where Src : EnumX<Proto=Proto>
, Dest : ExchangeFrom<Proto,(Indices,AA)>
{
fn exchange_from( src: Src ) -> Self {
Dest::exchange_from( src.into_proto() )
}
}
pub trait ExchangeInto<Dest,Indices> {
fn exchange_into( self ) -> Dest;
}
impl<Src,Dest,Indices> ExchangeInto<Dest,(Indices,AA)> for Src
where Dest: ExchangeFrom<Src,(Indices,AA)>
{
fn exchange_into( self ) -> Dest {
ExchangeFrom::<Src,(Indices,AA)>::exchange_from( self )
}
}
impl<Src,Dest,Proto,Indices> ExchangeInto<Dest,(Indices,AN)> for Src
where Dest : EnumX<Proto=Proto>
, Src : ExchangeInto<Proto,(Indices,AA)>
{
fn exchange_into( self ) -> Dest {
Dest::from_proto( self.exchange_into() )
}
}
pub struct LR<L,R> ( pub L, pub R );
pub struct V0;
pub struct Nil;
pub enum Enum0 {}
#[derive( Debug, PartialEq, Eq, PartialOrd, Ord )]
pub enum Enum1<T0> { _0(T0) }
impl<T0> FromVariant<T0,(V0,VA)> for Enum1<T0> {
fn from_variant( variant: T0 ) -> Self {
Enum1::_0( variant )
}
}
impl<T0> ExchangeFrom<Enum0,(Nil,AA)> for Enum1<T0> {
fn exchange_from( src: Enum0 ) -> Self { match src {} }
}
impl<T0> ExchangeFrom<Enum1<T0>,(V0,AA)> for Enum1<T0> {
fn exchange_from( src: Enum1<T0> ) -> Self {
match src {
Enum1::_0(v) => Enum1::_0(v)
}
}
}
include!( concat!( env!( "OUT_DIR" ), "/predefined.rs" ));
pub trait EnumX {
type Proto;
fn from_proto( src: Self::Proto ) -> Self;
fn into_proto( self ) -> Self::Proto;
}
impl<Variant,Enum,Proto,Index> FromVariant<Variant,(Index,VN)> for Enum
where Self : EnumX<Proto=Proto>
, Proto : FromVariant<Variant,(Index,VA)>
{
fn from_variant( variant: Variant ) -> Self {
Enum::from_proto( Proto::from_variant( variant ))
}
}
impl<Src,Dest,Proto,Indices> ExchangeFrom<Src,(Indices,AN)> for Dest
where Self : EnumX<Proto=Proto>
, Proto : ExchangeFrom<Src,(Indices,AA)>
{
fn exchange_from( src: Src ) -> Self {
Dest::from_proto( Proto::exchange_from( src ))
}
}
impl<Src,Dest,Proto,Indices> ExchangeInto<Dest,(Indices,NA)> for Src
where Self : EnumX<Proto=Proto>
, Proto : ExchangeInto<Dest,(Indices,AA)>
{
fn exchange_into( self ) -> Dest {
self.into_proto().exchange_into()
}
}
impl<Src,Dest,Proto,Indices> ExchangeFrom<Src,(Indices,NN)> for Dest
where Self : EnumX<Proto=Proto>
, Proto : ExchangeFrom<Src,(Indices,NA)>
{
fn exchange_from( src: Src ) -> Self {
Dest::from_proto( Proto::exchange_from( src ))
}
}
impl<Src,Dest,Proto,Indices> ExchangeInto<Dest,(Indices,NN)> for Src
where Self : EnumX<Proto=Proto>
, Proto : ExchangeInto<Dest,(Indices,AN)>
{
fn exchange_into( self ) -> Dest {
self.into_proto().exchange_into()
}
}
pub trait EnumxFrom<Src,Index> {
fn enumx_from( src: Src ) -> Self;
}
impl<Src,Dest,Index> EnumxFrom<Src,(Index,FV)> for Dest
where Dest : FromVariant<Src,Index>
{
fn enumx_from( src: Src ) -> Self { Dest::from_variant( src )}
}
impl<Src,Dest,Indices> EnumxFrom<Src,(Indices,XF)> for Dest
where Dest : ExchangeFrom<Src,Indices>
{
fn enumx_from( src: Src ) -> Self { Dest::exchange_from( src )}
}
pub trait IntoEnumx<Dest,Index> {
fn into_enumx( self ) -> Dest;
}
impl<Src,Dest,Index> IntoEnumx<Dest,Index> for Src
where Dest : EnumxFrom<Src,Index>
{
fn into_enumx( self ) -> Dest {
EnumxFrom::<Src,Index>::enumx_from( self )
}
}
#[cfg(test)]
mod tests {
use super::*;
mod test_unnamed {
use super::*;
#[test]
fn test_from_variant() {
let enum1 = Enum1::<i32>::from_variant( 2018 );
assert_eq!( enum1, Enum1::_0( 2018 ));
let enum2 = Enum2::<i32,String>::from_variant( "rust".to_string() );
assert_eq!( enum2, Enum2::_1( "rust".to_string() ));
let enum3 = Enum3::<i32,String,bool>::from_variant( true );
assert_eq!( enum3, Enum3::_2( true ));
}
#[test]
fn test_into_enum() {
let enum1: Enum1<i32> = 2018.into_enum();
assert_eq!( enum1, Enum1::_0( 2018 ));
let enum2: Enum2<i32,String> = "rust".to_string().into_enum();
assert_eq!( enum2, Enum2::_1( "rust".to_string() ));
let enum3: Enum3<i32,String,bool> = true.into_enum();
assert_eq!( enum3, Enum3::_2( true ));
}
#[test]
fn test_exchange_from() {
let enum1 = Enum1::<String>::from_variant( "rust".to_string() );
let enum1 = Enum1::<String>::exchange_from( enum1 );
assert_eq!( enum1, Enum1::_0( "rust".to_string() ));
let enum2 = Enum2::<i32,String>::exchange_from( enum1 );
assert_eq!( enum2, Enum2::_1( "rust".to_string() ));
let enum2 = Enum2::<String,i32>::exchange_from( enum2 );
assert_eq!( enum2, Enum2::_0( "rust".to_string() ));
let enum3 = Enum3::<bool,i32,String>::exchange_from( enum2 );
assert_eq!( enum3, Enum3::_2( "rust".to_string() ));
let enum3 = Enum3::<String,i32,bool>::exchange_from( enum3 );
assert_eq!( enum3, Enum3::_0( "rust".to_string() ));
}
#[test]
fn test_exchange_into() {
let enum1 = Enum1::<i32>::from_variant( 2018 );
let enum1: Enum1<i32> = enum1.exchange_into();
assert_eq!( enum1, Enum1::_0( 2018 ));
let enum2: Enum2<String,i32> = enum1.exchange_into();
assert_eq!( enum2, Enum2::_1( 2018 ));
let enum2: Enum2<i32,String> = enum2.exchange_into();
assert_eq!( enum2, Enum2::_0( 2018 ));
let enum3: Enum3<bool,String,i32> = enum2.exchange_into();
assert_eq!( enum3, Enum3::_2( 2018 ));
let enum3: Enum3<i32,String,bool> = enum3.exchange_into();
assert_eq!( enum3, Enum3::_0( 2018 ));
}
}
mod test_named {
mod enumx { pub use crate::EnumX; }
use super::*;
use enumx_derive::EnumX;
#[derive( EnumX, Debug, PartialEq, Eq, PartialOrd, Ord )]
enum One<T> { The(T) }
#[derive( EnumX, Debug, PartialEq, Eq, PartialOrd, Ord )]
enum Two<A,B> { Former(A), Latter(B) }
#[derive( EnumX, Debug, PartialEq, Eq, PartialOrd, Ord )]
enum Three<A,B,C> { First(A), Second(B), Third(C), }
#[test]
fn test_from_variant() {
let one = One::<i32>::from_variant( 2018 );
assert_eq!( one, One::The( 2018 ));
let two = Two::<i32,String>::from_variant( "rust".to_string() );
assert_eq!( two, Two::Latter( "rust".to_string() ));
let three = Three::<i32,String,bool>::from_variant( true );
assert_eq!( three, Three::Third( true ));
}
#[test]
fn test_into_enum() {
let one: One<i32> = 2018.into_enum();
assert_eq!( one, One::The( 2018 ));
let two: Two<i32,String> = "rust".to_string().into_enum();
assert_eq!( two, Two::Latter( "rust".to_string() ));
let three: Three<i32,String,bool> = true.into_enum();
assert_eq!( three, Three::Third( true ));
}
#[test]
fn test_exchange_from() {
let one = One::<i32>::from_variant( 2018 );
let enum1 = Enum1::<i32>::exchange_from( one );
let one = One::<i32>::exchange_from( enum1 );
let one = One::<i32>::exchange_from( one );
assert_eq!( one, One::The( 2018 ));
let two = Two::<String,i32>::exchange_from( one );
assert_eq!( two, Two::Latter( 2018 ));
let two = Two::<i32,String>::exchange_from( two );
assert_eq!( two, Two::Former( 2018 ));
let three = Three::<bool,String,i32>::exchange_from( two );
assert_eq!( three, Three::Third( 2018 ));
let three = Three::<i32,String,bool>::exchange_from( three );
assert_eq!( three, Three::First( 2018 ));
}
#[test]
fn test_exchange_into() {
let one = One::<String>::from_variant( "rust".to_string() );
let one: One<String> = one.exchange_into();
assert_eq!( one, One::The( "rust".to_string() ));
let two: Two<i32,String> = one.exchange_into();
assert_eq!( two, Two::Latter( "rust".to_string() ));
let two: Two<String,i32> = two.exchange_into();
assert_eq!( two, Two::Former( "rust".to_string() ));
let three: Three<bool,i32,String> = two.exchange_into();
assert_eq!( three, Three::Third( "rust".to_string() ));
let three: Three<String,i32,bool> = three.exchange_into();
assert_eq!( three, Three::First( "rust".to_string() ));
}
#[test]
fn test_adhoc_from_named() {
let three = Three::<bool,String,i32>::from_variant( 2018 );
let enum3 = Enum3::<String,i32,bool>::exchange_from( three );
assert_eq!( enum3, Enum3::_1( 2018 ));
}
#[test]
fn test_adhoc_into_named() {
let enum3 = Enum3::<String,i32,bool>::from_variant( 2018 );
let three: Three<bool,String,i32> = enum3.exchange_into();
assert_eq!( three, Three::Third( 2018 ));
}
#[test]
fn test_named_into_adhoc() {
let three = Three::<bool,String,i32>::from_variant( 2018 );
let enum3: Enum3<String,i32,bool> = three.exchange_into();
assert_eq!( enum3, Enum3::_1( 2018 ));
}
#[test]
fn test_named_from_adhoc() {
let enum3 = Enum3::<String,i32,bool>::from_variant( 2018 );
let three = Three::<bool,String,i32>::exchange_from( enum3 );
assert_eq!( three, Three::Third( 2018 ));
}
#[test]
fn test_enumx_from() {
let one = One::<i32>::enumx_from( 2018 );
let one = One::<i32>::enumx_from( one );
assert_eq!( one, One::The( 2018 ));
let two = Two::<String,i32>::enumx_from( one );
assert_eq!( two, Two::Latter( 2018 ));
let two = Two::<i32,String>::enumx_from( two );
assert_eq!( two, Two::Former( 2018 ));
let three = Three::<bool,String,i32>::enumx_from( two );
assert_eq!( three, Three::Third( 2018 ));
let three = Three::<i32,String,bool>::enumx_from( three );
assert_eq!( three, Three::First( 2018 ));
}
#[test]
fn test_enumx_into() {
let one: One<String> = "rust".to_string().into_enumx();
let one: One<String> = one.into_enumx();
assert_eq!( one, One::The( "rust".to_string() ));
let two: Two<i32,String> = one.into_enumx();
assert_eq!( two, Two::Latter( "rust".to_string() ));
let two: Two<String,i32> = two.into_enumx();
assert_eq!( two, Two::Former( "rust".to_string() ));
let three: Three<bool,i32,String> = two.into_enumx();
assert_eq!( three, Three::Third( "rust".to_string() ));
let three: Three<String,i32,bool> = three.into_enumx();
assert_eq!( three, Three::First( "rust".to_string() ));
}
}
}