Reputation: 450
In rust, I want in my impl fmt::Display for MainStruct
, to be able to print another struct.
#[derive(Clone, Default)]
pub struct MainStruct {
pub child: Option<ChildStruct>
}
#[derive(Clone, Default)]
pub struct ChildStruct {
pub field: String
}
impl std::fmt::Display for MainStruct {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "MainStruct: child:{}", self.child)
}
}
impl std::fmt::Display for ChildStruct {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "ChildStruct: field:{}", self.field)
}
}
I have tried with the default {}
formatter, and with the {:?}
formatter, but without any success.
Upvotes: 1
Views: 1931
Reputation: 10247
Since Option
does not implement Display
, you have to write some logic yourself to handle two possible cases. The simplest way might be to just match on the Option
explicitly:
impl std::fmt::Display for MainStruct {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "MainStruct: child: ")?;
match self.child.as_ref() {
Some(child) => write!(f, "Some({})", child),
None => write!(f, "None"),
}
}
}
Here's the playground with a short test case.
Upvotes: 3
Reputation: 441
The Problem is that Option<T>
has not implemented the Display
trait. So you have to get the value out of the option. The easiest to do so is .unwrap()
. This however panics if the option is None. (other methods for unpacking are expect
, match
, …)
If you use .unwrap()
the value is moved out of the Option. So the Option would now be invalid as it would not contain anything anymore. The compiler prevents this with an error cannot move out of 'self.child'
.
So what you actually want is a reference that does not consume the child. So you want &T
or &mut T
from the Option. You can do that by using the .as_ref()
to convert Option<T>
to Option<&T>
. Then if you do .unwrap()
on that the compiler wont complain anymore as you just copy a &T
pointer.
so your code compiles if you change the following:
impl std::fmt::Display for MainStruct {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "MainStruct: child:{}", self.child.as_ref().unwrap())
}
}
Upvotes: 2