Downcast a generic enum

pub enum Data<T> {
    Series(Vec<T>),
    Scalar(T),
}

Requirement 1: I want to put data of any T in a HashMap, i.e this HashMap can contain Series(f64), Series(f32), Scalar(i8) all at the same time.

To do this, currently my strategy (tell me if there is a better way) it to implement a trait

trait DataTrait {}
impl<T> DataTrait for Data<T> {}

So my HashMap could be defined as

HashMap<String, Box<dyn DataTrait>>

Requirements 2: I want to handle the value in the HashMap in another function. But I need to now the type of T and the variants of the enum.

fn handle_data(value: &dyn DataTrait) {
// How do I handle the value differently according to T and the enum's variants
}

If you know all the types that will ever be involved, use an enum instead of type erasure.

The Any trait is how you downcast.[1]

type Hm = HashMap<String, Box<dyn Any>>;

fn handle_data<T: 'static>(data: &dyn Any) {
    if let Some(data) = data.downcast_ref::<Data<T>>() {
        match data {
            Data::Series(vec) => {}
            Data::Scalar(scalar) => {}
        }
    }
}

Some code somewhere needs to know the original type (or potentially a set of possible types) for the function to be useful.


  1. More discussion here. ↩ī¸Ž

1 Like