pugio_lib/
lib.rs

1/*!
2`pugio-lib` is a library to generate, filter, and output dependency graphs of Rust projects,
3for dependency visualisation such as bloat or security auditing. It is used as the backend of
4the [`pugio`](https://crates.io/crates/pugio) CLI tool.
5
6It provides traits such as [`coloring::Gradient`], [`coloring::Values`], and
7[`template::Templating`] for full customisation of the generated graphs beyond only binary size
8analysis.
9
10# Example
11Here is a simple example of how to use `pugio-lib` to generate a dependency graph in DOT format,
12using custom defined templating, values and gradient implementations.
13
14```no_run
15use pugio_lib::graph::Graph;
16use pugio_lib::template::Templating;
17use pugio_lib::coloring::{Color, Gradient, Values};
18
19// Output of `cargo tree --edges=no-build,no-proc-macro,no-dev,features --prefix=depth --color=never ...`
20let cargo_tree_output = "...";
21// Output of `cargo bloat -n0 --message-format=json --crates ...`
22let cargo_bloat_output = "...";
23
24let mut graph = Graph::new(cargo_tree_output, cargo_bloat_output, false, None);
25
26// Remove dependencies more than 3 levels deep.
27graph.remove_deep_deps(3);
28
29// Remove all dependencies that are path or git specified.
30let iter = graph.node_indices().filter(|i| {
31    graph.node_weight(*i).extra().ends_with(")")
32}).collect::<Vec<_>>().into_iter();
33
34graph.remove_indices(iter);
35
36// Custom Gradient implementation.
37struct CustomGradient;
38
39impl Gradient for CustomGradient {
40    type Input = usize;
41
42    // Ignore `dark_mode` and `inverse` for simplicity.
43    fn color(&self, input: Self::Input, dark_mode: bool, inverse: bool) -> Color {
44        if input > 4096 {
45            Color {
46                r: 255,
47                g: 0,
48                b: 0,
49            }
50        } else {
51            Color {
52                r: 0,
53                g: 255,
54                b: 0,
55            }
56        }
57    }
58}
59
60// Custom Templating implementation.
61struct CustomTemplate;
62
63impl Templating for CustomTemplate {
64    type Context = bool;
65    type Value = &'static str;
66
67    fn node(
68        &self,
69        graph: &Graph,
70        index: usize,
71        value: Self::Value,
72        context: Self::Context,
73    ) -> (String, String) {
74        let tooltip = if context {
75            value.to_string()
76        } else {
77            "".to_string()
78        };
79        (graph.node_weight(index).short().to_string(), tooltip)
80    }
81
82    fn edge(
83        &self,
84        _graph: &Graph,
85        _source: usize,
86        _target: usize,
87    ) -> (String, String) {
88        ("".to_string(), "".to_string())
89    }
90}
91
92// Custom Values implementation.
93struct CustomValues(Vec<usize>);
94
95impl CustomValues {
96    fn new(graph: &Graph) -> Self {
97        let mut values = vec![0; graph.node_capacity()];
98        for index in graph.node_indices() {
99            let size = graph.size(index).unwrap_or_default();
100            values[index] = size;
101        }
102        Self(values)
103    }
104}
105
106impl Values for CustomValues {
107    type Context = bool;
108    type Value = &'static str;
109    type Output = usize;
110
111    fn context(&self) -> Self::Context {
112        true
113    }
114
115    fn value(&self, index: usize) -> Self::Value {
116        if self.0[index] > 4096 {
117            "large"
118        } else {
119            "small"
120        }
121    }
122
123    fn output(&self, index: usize) -> Self::Output {
124        self.0[index]
125    }
126}
127
128let custom_values = CustomValues::new(&graph);
129
130// Output the graph in DOT format.
131let dot_output = graph.output_dot(&Default::default(), &CustomTemplate, &custom_values, &CustomGradient);
132```
133*/
134
135mod cargo;
136pub mod coloring;
137pub mod error;
138pub mod graph;
139pub mod template;