Recursively print struct in `fmt::Display`
Asked Answered
S

2

6

I'm currently in the process of implementing fmt::Display for a struct so that it will print out to the console. However The struct has a field which is a Vec of it's type.

Struct

pub struct Node<'a> {
    pub start_tag: &'a str,
    pub end_tag: &'a str,
    pub content: String,
    pub children: Vec<Node<'a>>,
}

Current fmt::Display (invalid)

impl<'a> fmt::Display for Node<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "START TAG: {:?}", self.start_tag);
        write!(f, "CONTENT: {:?}", self.content);
        for node in self.children {
            write!(f, "CHILDREN:\n\t {:?}", node);
        }
        write!(f, "END TAG: {:?}", self.end_tag);
    }
}

Desired Output

START TAG: "Hello"
CONTENT: ""
CHILDREN:
   PRINTS CHILDREN WITH INDENT
END TAG: "World"
Smoking answered 27/6, 2015 at 1:45 Comment(1)
for node in self.childrenfor node in &self.children. Also use try!() around each write. (welcome to format this into an answer.)Carlie
A
6

There is a (somewhat hidden) feature of Debug, you can use the format specifier {:#?} to pretty-print your object (with indents and multiple lines). If you rewrite your struct's elements to have the same order as your requested output and derive the Debug trait

#[derive(Debug)]
pub struct Node<'a> {
    pub start_tag: &'a str,
    pub content: String,
    pub children: Vec<Node<'a>>,
    pub end_tag: &'a str,
}

then your output can look like this:

Node {
    start_tag: "Hello",
    content: "",
    children: [
        Node {
            start_tag: "Foo",
            content: "",
            children: [],
            end_tag: "Bar"
        }
    ],
    end_tag: "World"
}

Try it out in the PlayPen

Atc answered 27/6, 2015 at 9:18 Comment(0)
E
4

It seems you are confusing Display and Debug.

{:?} uses the Debug trait for formatting. You probably didn't implement Debug on your type, which is why you'd get an error. To use the Display trait, write {} in your format string.

write!(f, "CHILDREN:\n\t {}", node);
Eloiseelon answered 27/6, 2015 at 1:49 Comment(1)
Semantically this sort of output is far more likely to be suitable for Debug than Display, incidentally.Officialese

© 2022 - 2024 — McMap. All rights reserved.