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