[][src]Trait structural::enums::VariantCount

pub unsafe trait VariantCount {
    type Count: IsTStr;
}

For querying the amount of variants of an enum.

Safety

Count must be a TStr with the amount of enum variants written in decimal. For example:TS!(9) would be used for an enum with 9 variants.

Implementors who specify fewer variants than the enum actually has may result in undefined behavior when the enum is matched in the switch macro.

Example

This example demonstrates using VariantCount as a bound to restrict a pre-existing structural alias.

use structural::{Structural,TS,structural_alias,switch};
use structural::enums::VariantCount;

{
    // Enum

    assert_eq!( nonexhaustive(Enum::Foo), Some(0) );
    assert_eq!( exhaustive_a(Enum::Foo), 0 );
    assert_eq!( exhaustive_b(Enum::Foo), 0 );
    
    let bar=Enum::Bar(0);
    assert_eq!( nonexhaustive(bar.clone()), Some(1) );
    assert_eq!( exhaustive_a(bar.clone()), 1 );
    assert_eq!( exhaustive_b(bar), 1 );
    
    let baz=Enum::Baz{wha:"whoah".into()};
    assert_eq!( nonexhaustive(baz.clone()), Some(2) );
    assert_eq!( exhaustive_a(baz.clone()), 2 );
    assert_eq!( exhaustive_b(baz), 2 );
}
{   
    // HyperEnum:
    // This enum has a superset of the variants required by `Ternary`.
    // The commented out lines below don't compile
    // because the `exhaustive_*` functions require the enum to only have
    // the `Foo`,`Bar`,and `Baz` variants

    assert_eq!( nonexhaustive(HyperEnum::Foo), Some(0) );
    // assert_eq!( exhaustive_a(HyperEnum::Foo), 0 );
    // assert_eq!( exhaustive_b(HyperEnum::Foo), 0 );
    
    assert_eq!( nonexhaustive(HyperEnum::Bar), Some(1) );
    // assert_eq!( exhaustive_a(HyperEnum::Bar), 1 );
    // assert_eq!( exhaustive_b(HyperEnum::Bar), 1 );
    
    assert_eq!( nonexhaustive(HyperEnum::Baz), Some(2) );
    // assert_eq!( exhaustive_a(HyperEnum::Baz), 2 );
    // assert_eq!( exhaustive_b(HyperEnum::Baz), 2 );

    assert_eq!( nonexhaustive(HyperEnum::Boom), None );
}

// This function returns the index of the current variant of the enum,
// but because `Ternary` is a nonexhaustive structural trait,
// it returns None to handle the case where the enum is
// none of the three variants.
//
fn nonexhaustive<T>(this: T)->Option<u8>
where
    T: Ternary,
{
    // The VariantCount bound allow this switch to be exhaustive.
    switch!{this;
        Foo=>Some(0),
        Bar=>Some(1),
        Baz=>Some(2),
        // This branch is required,
        // because `Ternary` doesn't require the enum to have exactly 3 variants
        _=>None,
    }
}

// This function returns the index of the current variant of the enum,
fn exhaustive_a<T>(this: T)->u8
where
    T: Ternary + VariantCount<Count=TS!(3)>,
{
    // The VariantCount bound allow this switch to be exhaustive.
    switch!{this;
        Foo=>0,
        Bar=>1,
        Baz=>2,
    }
}

fn exhaustive_b<T>(this: T)->u8
where
    // `TernaryExhaustive` is equivalent to `Ternary + VariantCount<Count=TS!(3)>`.
    //
    // You would use a `+ VariantCount<Count=_>` bound if all of thse happen:
    // - The structural alias came from somewhere else.
    // - It's a nonexhaustive structural alias.
    // - You don't want to do declare another alias,like `TernarySuper`.
    T: TernaryExhaustive
{
    exhaustive_a(this)
}

structural_alias!{
    // `#[struc(and_exhaustive_enum(...))]` generates a subtrait with
    //`VariantCount<Count=TS!($variant_count)>` as an additional bound
    // (the `$variant_count` stands for the number of variants in the structural alias)
    #[struc(and_exhaustive_enum(name="TernaryExhaustive"))]
    pub trait Ternary{
        Foo,
        Bar,
        Baz,
    }

    pub trait TernarySuper: Ternary + VariantCount<Count=TS!(3)> {}
}

#[derive(Structural,Clone)]
enum Enum{
    Foo,
    Bar(u32),
    Baz{wha:String},
}

#[derive(Structural,Clone)]
enum HyperEnum{
    Foo,
    Bar,
    Baz,
    Boom,
}

Associated Types

type Count: IsTStr

This is a TStr (eg:TS!(3)) representing the amount of variants of the enum.

This is a type instead of a &'static str constant so that it can be a supertrait of dyn-compatible traits.

Loading content...

Implementations on Foreign Types

impl<T> VariantCount for Option<T>[src]

type Count = str_2

impl<T, E> VariantCount for Result<T, E>[src]

type Count = str_2

impl<T> VariantCount for ManuallyDrop<T> where
    T: VariantCount
[src]

impl<P> VariantCount for Pin<P> where
    P::Target: VariantCount,
    P: Deref,
    P::Target: Sized
[src]

impl<T> VariantCount for Arc<T> where
    T: VariantCount,
    T: ?Sized
[src]

impl<T> VariantCount for Rc<T> where
    T: VariantCount,
    T: ?Sized
[src]

impl<T> VariantCount for Box<T> where
    T: VariantCount,
    T: ?Sized
[src]

impl<'a, T> VariantCount for &'a T where
    T: VariantCount,
    T: ?Sized
[src]

impl<'a, T> VariantCount for &'a mut T where
    T: VariantCount,
    T: 'a + ?Sized
[src]

Loading content...

Implementors

impl<T> VariantCount for FieldCloner<T> where
    T: VariantCount
[src]

impl<T> VariantCount for StrucWrapper<T> where
    T: VariantCount
[src]

Loading content...