rapx/analysis/core/api_dependency/graph/
serialize.rs

1use super::dep_edge::DepEdge;
2use super::dep_node::DepNode;
3use crate::analysis::core::api_dependency::ApiDependencyGraph;
4use serde::{
5    ser::{SerializeMap, SerializeSeq},
6    Serialize,
7};
8use std::path::Path;
9
10#[derive(Serialize, Debug)]
11struct NodeInfo {
12    id: usize,
13    kind: String,
14    path: String,
15    args: Vec<String>,
16}
17
18#[derive(Serialize, Debug)]
19struct EdgeInfo {
20    id: usize,
21    kind: String,
22    from: usize,
23    to: usize,
24}
25
26impl<'tcx> ApiDependencyGraph<'tcx> {
27    pub fn dump_to_json(&self, path: impl AsRef<Path>) -> std::io::Result<()> {
28        let file = std::fs::File::create(path)?;
29        serde_json::to_writer_pretty(file, self)?;
30        Ok(())
31    }
32}
33
34impl<'tcx> Serialize for ApiDependencyGraph<'tcx> {
35    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
36    where
37        S: serde::Serializer,
38    {
39        let mut map = serializer.serialize_map(Some(2))?;
40        let mut nodes = Vec::new();
41        for index in self.graph.node_indices() {
42            let node_info = match self.graph[index] {
43                DepNode::Api(fn_did, args) => NodeInfo {
44                    id: index.index(),
45                    kind: "api".to_owned(),
46                    path: self.tcx.def_path_str(fn_did),
47                    args: args.iter().map(|arg| arg.to_string()).collect(),
48                },
49                DepNode::Ty(ty) => NodeInfo {
50                    id: index.index(),
51                    kind: "type".to_owned(),
52                    path: ty.ty().to_string(),
53                    args: vec![],
54                },
55            };
56            nodes.push(node_info);
57        }
58        let mut edges = Vec::new();
59        for index in self.graph.edge_indices() {
60            let kind = match self.graph[index] {
61                DepEdge::Arg(no) => "arg".to_owned(),
62                DepEdge::Ret => "ret".to_owned(),
63                DepEdge::Transform(kind) => format!("transform({})", kind),
64            };
65            let (from, to) = self.graph.edge_endpoints(index).unwrap();
66            let (from, to) = (from.index(), to.index());
67            edges.push(EdgeInfo {
68                id: index.index(),
69                kind: "arg".to_owned(),
70                from,
71                to,
72            });
73        }
74        map.serialize_entry("nodes", &nodes)?;
75        map.serialize_entry("edges", &edges)?;
76        map.end()
77    }
78}