I am struggling with returning a common trait, given lines I have currently:
#[derive(Debug)]
pub struct GroupAddressThreeLevel {
main: u8,
middle: u8,
sub: u8,
}
#[derive(Debug)]
pub struct GroupAddressTwoLevel {
main: u8,
sub: u16,
}
pub trait GroupAddressBytes {
fn as_bytes(&self) -> [u8; 2];
fn from_bytes(bytes: [u8; 2]) -> Result<Self, CustomError> where Self : Sized;
}
impl GroupAddressBytes for GroupAddressThreeLevel {
pub fn new(main: u8, middle: u8, sub: u8) -> Result<Self, CustomError> {
... omitted ...
}
}
impl GroupAddressBytes for GroupAddressTwoLevel {
pub fn new(main: u8, sub: u16) -> Result<Self, CustomError> {
... omitted ...
}
}
impl GroupAddress {
pub fn parse(address: &str) -> Result<dyn GroupAddressBytes, CustomError> {
let splitted_address: Vec<_> = address.split('/').collect();
match splitted_address.len() {
3 => {
// Group Address is Three-level
GroupAddressThreeLevel::new(
u8::from_str(splitted_address[0]).unwrap(),
u8::from_str(splitted_address[1]).unwrap(),
u8::from_str(splitted_address[2]).unwrap(),
)
}
2 => {
// Group Address is Two-Level
GroupAddressTwoLevel::new(
u8 ::from_str(splitted_address[0]).unwrap(),
u16::from_str(splitted_address[1]).unwrap(),
)
}
_ => {
Err(CustomError(format!("Unsupported address format provided. Supported are: 0/0/0 or 0/0")))
}
}
}
}
What I am getting from compiler is:
37 | pub fn parse(address: &str) -> Result<dyn GroupAddressBytes, CustomError> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
According to https://doc.rust-lang.org/reference/items/traits.html#object-safety it seems be object safe as I added "Self : Sized" to the method of GroupAddressBytes trait.
How can I accomplish that GroupAddress#parse(&str) function will compile successfully and return the GroupAddressBytes as an object?
The idea of GroupAddress#parse(&str) function is when user provides format "0/0/0" then GroupAddressThreeLevel is returned, if "0/0" is provided then GroupAddressTwoLevel is returned. Both structs will have their own implementation which varies bit differently, but share the same methods provided by GroupAddressBytes.
Alternatively, if the approach above is not possible with Rust, what about following approach. Here I also failed:
pub fn parse<T : GroupAddressBytes>(address: &str) -> Result<T, CustomError> {
which returns by compiler:
expected type parameter `T`, found struct `GroupAddressThreeLevel`
expected type parameter `T`, found struct `GroupAddressTwoLevel`
Thank you, Christoph