Home > Software design >  Create enum of generic variants of a type
Create enum of generic variants of a type

Time:06-27

I have a struct with a constant generic parameter VAR. This parameter is used in methods, improving the runtime speed, due to large amount of comparisons can be done compile time. It's rather difficult to store and pass around a generic type everywhere. I have a fixed number of variants, I could list in an enum SquirrelVariant, I can pass around easier, and use match to branch out to generic functions. Creating the enum from a Squirrel<VAR> is rather difficult, rust doesn't seem to allow compile time match or anything like that.

struct Squirrel<const VAR: u8>
{
}


enum SquirrelVariant
{
    V1(Squirrel<1>),
    V2(Squirrel<2>),
    V3(Squirrel<3>),
}

// failed attempt 1)
fn make_squirrel_variant<const VAR: u8>(s: Squirrel<VAR>) -> SquirrelVariant
{
    match VAR {
        1 => SquirrelVariant::V1(s), // expected `1_u8`, found `VAR`
        2 => SquirrelVariant::V2(s), // expected `2_u8`, found `VAR`
        3 => SquirrelVariant::V3(s), // expected `3_u8`, found `VAR`
    }
}


// failed attempt 2)
impl From<Squirrel<1>> for SquirrelVariant
{
    fn from(s: Squirrel<1>) -> Self
    {
        SquirrelVariant::V1(s)
    }
}

impl From<Squirrel<2>> for SquirrelVariant
{
    fn from(s: Squirrel<2>) -> Self
    {
        SquirrelVariant::V2(s)
    }
}

impl From<Squirrel<3>> for SquirrelVariant
{
    fn from(s: Squirrel<3>) -> Self
    {
        SquirrelVariant::V3(s)
    }
}

fn make_squirrel_variant2<const VAR: u8>(s: Squirrel<VAR>) -> SquirrelVariant
{
    s.into() // the trait `From<Squirrel<VAR>>` is not implemented for `SquirrelVariant`
    // = help: the following implementations were found:
    //     <SquirrelVariant as From<Squirrel<1_u8>>>
    //     <SquirrelVariant as From<Squirrel<2_u8>>>
    //     <SquirrelVariant as From<Squirrel<3_u8>>>
}

https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=54ec536a9d84d13b4b3ae16180022ba8

CodePudding user response:

You can use the following trick to resolve the type errors:

struct Squirrel<const VAR: u8> {}

impl<const VAR: u8> Squirrel<VAR> {
    fn transmute_squirrel_type<const VAR2: u8>(self) -> Squirrel<VAR2> {
        if VAR == VAR2 {
            Squirrel { }
        } else {
            unreachable!()
        }
    }
}


enum SquirrelVariant
{
    V1(Squirrel<1>),
    V2(Squirrel<2>),
    V3(Squirrel<3>),
}

impl<const VAR: u8> Squirrel<VAR> {
    fn to_variant(self) -> SquirrelVariant {
        match VAR {
            1 => SquirrelVariant::V1(self.transmute_squirrel_type()),
            2 => SquirrelVariant::V2(self.transmute_squirrel_type()),
            3 => SquirrelVariant::V3(self.transmute_squirrel_type()),
            _ => unreachable!()
        }
    }
}
  • Related