I don’t have a single use case, I feel like that’s something I need very often.
Today for example I have started a project to collect metrics from different system.
This is meant to grow, have many different system and many different kind of events.
So I want something like :
trait Event<T> where T: serde::Serialize {
fn get_event_type_id(&self) -> String,
fn get_content(&self) -> T;
}
trait EventCollector<E, T> where E:Event<T>, T: serde::Serialize {
fn collect_events(&self) -> Iter<E>
}
Obviously this won’t compile, because all the traits I am returning. Those traits are not even object safe. Serde objects themselves are not object safe, you have to use erased-serde which fills like a big hack and would confuse even more my colleagues…
So 3 choices I can think of:
- Make my trait object safe, box everything. Besides all the obvious complications, there’s some negative effect on the rest of my code because in some scenarios I want to retrieve one specific events and the boxing is unnecessary. Designing for both scenarios complicates my code by a lot.
- Have an enum containing all my events and enum of enums to be able to scale with many events; Define
get_event_type_id at the enum level (which in my case is awkward because the type_id is deduce from the content); having this weird enum, that I was referring to
enum JenkinsEvents{
StartBuildEvent(StartBuildEvent),
SuccesBuildEvent(SuccesBuildEvent),
....
}
- Redesign how collecting events works to use a visitor-like pattern. Won’t go in details about that, Rust is not the problem here, it just that it make the code unnecessarily tightly coupled and makes it much less nicer for the consumer of the API.
If I had sealed trait or something similar almost all my problems are gone. I can return a sized type (because we know all the variants) which implements a trait. The trait is implemented per Event type (no awkward pattern matching like with enum).
What I want is a sum type (sized, like enum) that can implement a trait by forcing all its member to implement the trait.
Cherry on top, similar to traits, you can start do monomorphization and have zero cost abstraction. All the benefits of both traits and enums in one…