I'm wondering if anyone has experience with modeling an enum-like type as a trait. I'm working with a radio peripheral that supports pre-configuring up to 8 addresses to be used when sending and receiving data. I want to model this via a trait that can be implemented and is passed as a generic parameter to the radio type:
pub trait Address {
...
}
pub struct Radio<A: Address> {
...
}
impl<A: Address> Radio<A> {
fn new() -> Radio<A> { ... }
fn listen(&mut self, addresses: &[A])
-> impl Stream<Item = (A, [u8; 25]), Error = !> + '_
{ ... }
fn send(&mut self, address: A, packet: [u8; 25])
-> impl Future<Item = (), Error = !> + '_
{ ... }
...
}
Internally once configured the radio will only use integers to refer to these addresses, during configuration it needs some more data from the address trait, for simplicities sake lets assume the addresses are just strings:
pub trait Address {
fn name(&self) -> &str;
...
}
My first attempt at making Address
represent an enum-like type is simply a pair of constant array and get index function:
pub trait Address: Sized + Copy {
const ADDRESSES: [Self; 8];
fn name(&self) -> &str;
fn index(&self) -> usize;
}
This works, but it doesn't provide any real compile time guarantees, this could be implemented for a type with more than 8 possible values, and there's nothing ensuring <A as Address>::ADDRESSES[5].index() == 5
or a.index() < 8
.
So, anyone have ideas on a good way to do this? Or should I just give up on letting the user provide their own enum type and just force them to match on my own pub enum Address { One, Two, ... }
.