impl Decodable for DataUnit {
fn decode<D: AsRef<[u8]> + ?Sized>(data: &D) -> Self {
let data = Vec::from(data.as_ref());
let len = data.len();
let data = data.as_slice();
let mut index = 0;
let data_type = DataType::decode(data);
index += data_type.len();
let data_code = DataCode::decode(&data[index..]);
index += data_code.len();
let mut items: Vec<Box<dyn ProtocolDatable>> = Vec::new();
macro_rules! match_arm {
($Item:ident) => {{
loop {
if index >= len {
break;
}
let item = $Item::decode(&data[index..]);
index += item.len();
items.push(Box::new(item));
}
Self { data_type, data_code, items, }
}}
}
match data_type {
DataType::Ack => match_arm!(AckItem),
DataType::ParamSet => match_arm!(ParamSetItem),
DataType::VehicleCtrl => match_arm!(VehicleCtrlItem),
DataType::BlueKey => match_arm!(BlueKeyItem),
DataType::BlueKeyV2 => match_arm!(BlueKeyItemV2),
DataType::ParamQuery => match_arm!(ParamQueryItem),
DataType::DataReport => match_arm!(ReportItem),
DataType::FileTrans => match_arm!(FileItem),
}
}
}
I think, this can probably be made to work with some fn definition, too (closure would have been my first thought, by those cannot be generic, so taking a type like AckItem/ParamSetItem/... as generic parameter doesn’t work) though it’s harder to test this approach for me without having the types present in a complete example where I could ask the compiler “does it compile yet?”
Probably just needs a + 'static in the right place. Creating Box<dyn ProtocolDatable>, which is shorthand for Box<dyn ProtocolDatable + 'static> requires the boxed type to be valid for 'static lifetime.
72 | items.push(item);
| ^^^^
| |
| the parameter type `T` must be valid for the static lifetime...
| ...so that the type `T` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound
|
63 | T: Decodable + LengthComputable + ProtocolDatable + 'static {
| +++++++++
82 | decode_items::<dyn ProtocolDatable>(data, &mut index, len, data_type, data_code)
| ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `dyn ProtocolDatable`
note: required by a bound in `decode_items`
On an unrelated note, given the supetrait bounds of ProtocolDatable that you shared, the T: Decodable + LengthComputable + ProtocolDatable + 'static in line 64 can probably be shortened to just T: ProtocolDatable + 'static.
As a trait bound, it means the type does not contain any non-static references. Eg. the receiver can hold on to the type for as long as they want and it will never become invalid until they drop it.