I have around 10 structs with between 5-10 fields each and I want to be able to print them out using the same format.
Most of my structs look like this:
struct Example {
a: Option<String>,
b: Option<i64>,
c: Option<String>,
... etc
}
I would like to be able to define a impl for fmt::Display without having to enumerate the fields again so there is no chance for missing one if a new one is added.
For the struct:
let eg = Example{
a: Some("test".to_string),
b: Some(123),
c: None,
}
I would like the output format:
a: test
b: 123
c: -
I currently am using #[derive(Debug)] but I don't like that it prints out Some(X) and None and a few other things.
If I know that all the values inside my structs are Option<T: fmt::Display> can I generate myself a Display method without having to list the fields again?
This may not be the most minimal implementation, but you can derive serialisable and use the serde crate. Here's an example of a custom serialiser: https://serde.rs/impl-serializer.html
In your case it may be much simpler (you need only a handful of types and can panic/ignore on anything unexpected).
Another approach could be to write a macro and create your own lightweight serialisation solution.
I ended up solving this with a macro. While it is not ideal it does the job.
My macro currently looks like this:
macro_rules! MyDisplay {
($struct:ident {$( $field:ident:$type:ty ),*,}) => {
#[derive(Debug)]
pub struct $struct { pub $($field: $type),*}
impl fmt::Display for $struct {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
$(
write!(f, "{}: {}\n",
stringify!($field).to_string(),
match &self.$field {
None => "-".to_string(),
Some(x) => format!("{:#?}", x)
}
)?;
)*
Ok(())
}
}
};
}
Which can be used like this:
MyDisplay! {
Example {
a: Option<String>,
b: Option<i64>,
c: Option<String>,
}
}
Playground with an example: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=cc089f8aecaa04ce86f3f9e0307f8785
My macro is based on the one here https://stackoverflow.com/a/54177889/1355121 provided by Cerberus
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With