I'm using generics specialization to have custom compile time type on some enum data structure :
pub trait MyEnumState{}
// All state are Zero Sized Type
pub struct State1; impl MyEnumState for State1{};
pub struct State2; impl MyEnumState for State2{};
// Note : I don't know is there is a PhantomData<S> for an enum
pub enum MyEnum<S: MyEnumState> {
A,
B,
C(i32), // Can also have some data
// ... long enum
}
Now I would like to be able to cast them around : same value, different type
// How to avoid this mess ???
impl MyEnum<State1> {
pub fn to_state2(self) -> MyEnum<State2> {
match self {
MyEnum::A => MyEnum::A,
MyEnum::B => MyEnum::B,
MyEnum::C(v) => MyEnum::C(v),
}
}
}
// I can proably make a generic function
// ```
// fn cast
// <StateBegin : MyEnumState, StateEnd : MyEnumState>
// (val MyEnum<StateBegin>) -> MyEnum<StateEnd> { ... }
// ```
// to avoid repetition but I still have at least 1 giant match to implement
impl MyEnum<State2> { ... }
impl<S : MyEnumState> MyEnum<S>
{
pub fn to_state<NewState : MyEnumState>(self) -> MyEnum<NewState>
{
// how ?!
}
}
This is just a simple example, the goal is to have 0 match statements to avoid matching for all existing enum variant.
One way is to put the PhantomData
field outside of the enum in a wrapper struct:
use core::marker::PhantomData;
pub enum MyEnum {
A,
B,
C(i32),
}
pub struct EnumWithState<S: MyEnumState> {
data: MyEnum,
_state: PhantomData<S>,
}
Then you can implement the type casting function on EnumWithState
:
impl<S: MyEnumState> EnumWithState<S> {
fn to_state<S2: MyEnumState>(self) -> EnumWithState<S2> {
EnumWithState {
data: self.data,
_state: PhantomData,
}
}
}