--> src/parser.rs:70:32
|
70 | key: event.md5.0.to_owned(),
| ^^^
error: aborting due to previous error
Basically I am trying to build a parser for multiple event types after they have been decoded and would like to avoid duplicate code however it seems by making the type generic it doesn't know how to handle the struct.
In this context, event's type is a generic type parameter, and in Rust you cannot perform field access on an abstract type (yet).
You have two solutions:
encoding the common behavior of "getting that field" within a method of some trait
trait GetMd5 {
fn md5 (self: &'_ Self)
-> &'_ ... // type of md5 field here
;
}
impl GetMd5 for Event1 {
#[inline]
fn md5 (self: &'_ Self)
-> &'_ ... // type of md5 field here
{
&self.md5
}
}
fn some_fun<P>(&self, obj: EventObj)
where
P : GetMd5,
{
...
key: event.md5().0.to_owned(),
}
slightly cumbersome, but the recommended way to go
another form of polymorphism: macro-based "duck typing"
// to be defined "in the middle" of your function, when `obj` is in scope
macro_rules! EventKey_match_all {(
$( $EventN:ident ),* $(,)?
=> (match ... {
$(
e @ EventKey::$EventN => {
json::from_value::<$EventN>(obj)
.map_err(|err| EventError::DecodeEventError(e.clone(), err, None))
.map(|event| EventMessage {
header: hdr,
key: event.md5.0.to_owned(),
event,
}})
},
)*
})}
EventKey_match_all!( Event1, Event2, ... )
this is better if you end up having many places where you want to factor out code, and defining all the right traits and method getters for it to work leads to writing more code than the generic function saves you from typing