webpack_q/graphs/
ser.rs

1/*
2 * Copyright [2022] [Kevin Velasco]
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17use crate::graphs::ModuleParentGraph;
18use meshed::graph::node::Node;
19use meshed::graph::Inverted;
20use std::collections::HashSet;
21
22use meshed::prelude::*;
23use serde::ser::SerializeMap;
24use serde::{Serialize, Serializer};
25
26use std::marker::PhantomData;
27use webpack_stats::chunk::ChunkId;
28use webpack_stats::import::ImportType;
29
30pub struct GraphSerialization<T, K> {
31    graph: T,
32    kind: PhantomData<K>,
33}
34
35impl<T, K> GraphSerialization<T, K> {
36    pub fn new<Kind>(graph: T) -> GraphSerialization<T, Kind> {
37        GraphSerialization {
38            graph,
39            kind: Default::default(),
40        }
41    }
42}
43
44pub struct NodeEdge;
45
46type ModuleEdgeSer = GraphSerialization<Inverted<ModuleParentGraph>, NodeEdge>;
47
48impl Serialize for ModuleEdgeSer {
49    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
50    where
51        S: Serializer,
52    {
53        let mut map_serializer = serializer.serialize_map(Some(2))?;
54        map_serializer.serialize_key("nodes")?;
55
56        struct NodeSerializer(Node<ModuleParentGraph>);
57
58        impl Serialize for NodeSerializer {
59            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
60            where
61                S: Serializer,
62            {
63                let mut map = serializer.serialize_map(Some(3))?;
64                map.serialize_key("id")?;
65                map.serialize_value(&self.0.get_id().to_string())?;
66                if let Some(value) = self.0.get_annotation::<ChunkId>() {
67                    map.serialize_key("chunk")?;
68                    map.serialize_value(&value.0)?;
69                } else {
70                    map.serialize_key("chunk")?;
71                    map.serialize_value(&None as &Option<()>)?;
72                }
73
74                map.serialize_key("label")?;
75                map.serialize_value(&self.0.label().to_string())?;
76                map.end()
77            }
78        }
79
80        let nodes = self
81            .graph
82            .inner()
83            .all_nodes()
84            .map(NodeSerializer)
85            .collect::<Vec<_>>();
86
87        map_serializer.serialize_value(&nodes)?;
88
89        struct EdgeSerializer(meshed::graph::edge::Edge<ModuleParentGraph>);
90
91        impl Serialize for EdgeSerializer {
92            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
93            where
94                S: Serializer,
95            {
96                let mut map = serializer.serialize_map(Some(4))?;
97
98                map.serialize_key("source")?;
99                map.serialize_value(self.0.origin.get_id().0.as_ref())?;
100                map.serialize_key("target")?;
101                map.serialize_value(self.0.target.get_id().0.as_ref())?;
102                map.serialize_key("async")?;
103                map.serialize_value(&matches!(
104                    self.0.meta.as_ref().0,
105                    ImportType::RequireContext | ImportType::Import | ImportType::ImportDynamic
106                ))?;
107
108                map.serialize_key("importer")?;
109                map.serialize_value(&self.0.meta.as_ref().1 .0)?;
110
111                map.end()
112            }
113        }
114        let mut seen_set = HashSet::new();
115        let edges = self
116            .graph
117            .inner()
118            .all_edges()
119            .filter(|edge| {
120                if seen_set.contains(&edge.get_id()) {
121                    false
122                } else {
123                    seen_set.insert(edge.get_id());
124                    true
125                }
126            })
127            .map(EdgeSerializer)
128            .collect::<Vec<_>>();
129
130        map_serializer.serialize_key("edges")?;
131        map_serializer.serialize_value(&edges)?;
132        map_serializer.end()
133    }
134}