ptree/
graph.rs

1use crate::item::TreeItem;
2use crate::output::{print_tree, write_tree_with};
3use crate::print_config::PrintConfig;
4use crate::style::Style;
5
6use std::borrow::Cow;
7use std::fmt::Display;
8use std::io;
9
10use petgraph::graph::IndexType;
11use petgraph::prelude::*;
12use petgraph::EdgeType;
13
14impl<'a, N, E, Ty, Ix> TreeItem for (&'a Graph<N, E, Ty, Ix>, NodeIndex<Ix>)
15where
16    Ty: EdgeType,
17    Ix: IndexType,
18    N: Clone + Display,
19    E: Clone,
20{
21    type Child = Self;
22
23    fn write_self<W: io::Write>(&self, f: &mut W, style: &Style) -> io::Result<()> {
24        if let Some(w) = self.0.node_weight(self.1) {
25            write!(f, "{}", style.paint(w))
26        } else {
27            Ok(())
28        }
29    }
30
31    fn children(&self) -> Cow<[Self::Child]> {
32        let v: Vec<_> = self.0.neighbors(self.1).map(|i| (self.0, i)).collect();
33        Cow::from(v)
34    }
35}
36
37///
38/// Print `graph`, starting at node `start`, to standard output using default
39/// formatting
40pub fn print_graph<N, E, Ty, Ix>(graph: &Graph<N, E, Ty, Ix>, start: NodeIndex<Ix>) -> io::Result<()>
41where
42    Ty: EdgeType,
43    Ix: IndexType,
44    N: Clone + Display,
45    E: Clone,
46{
47    print_tree(&(graph, start))
48}
49
50///
51/// Write `graph`, starting at node `start`, to writer `f` using custom
52/// formatting
53pub fn write_graph_with<N, E, Ty, Ix, W: io::Write>(
54    graph: &Graph<N, E, Ty, Ix>,
55    start: NodeIndex<Ix>,
56    f: W,
57    config: &PrintConfig,
58) -> io::Result<()>
59where
60    Ty: EdgeType,
61    Ix: IndexType,
62    N: Clone + Display,
63    E: Clone,
64{
65    write_tree_with(&(graph, start), f, config)
66}
67
68#[cfg(test)]
69mod tests {
70    use super::*;
71    use std::io::Cursor;
72    use std::str::from_utf8;
73
74    #[test]
75    fn small_graph_output() {
76        let mut deps = Graph::<&str, &str>::new();
77        let pg = deps.add_node("petgraph");
78        let fb = deps.add_node("fixedbitset");
79        let qc = deps.add_node("quickcheck");
80        let rand = deps.add_node("rand");
81        let libc = deps.add_node("libc");
82        deps.extend_with_edges(&[(pg, fb), (pg, qc), (qc, rand), (rand, libc), (qc, libc)]);
83
84        let config = PrintConfig {
85            indent: 4,
86            leaf: Style::default(),
87            branch: Style::default(),
88            ..PrintConfig::default()
89        };
90
91        let mut cursor: Cursor<Vec<u8>> = Cursor::new(Vec::new());
92
93        write_graph_with(&deps, pg, &mut cursor, &config).unwrap();
94
95        let data = cursor.into_inner();
96        let expected = "\
97                        petgraph\n\
98                        ├── quickcheck\n\
99                        │   ├── libc\n\
100                        │   └── rand\n\
101                        │       └── libc\n\
102                        └── fixedbitset\n\
103                        ";
104        assert_eq!(from_utf8(&data).unwrap(), expected);
105    }
106}