Skip to main content

petgraph/graph_impl/stable_graph/
serialization.rs

1use serde::de::Error;
2use serde::{Deserialize, Deserializer, Serialize, Serializer};
3
4use std::marker::PhantomData;
5
6use crate::prelude::*;
7
8use crate::graph::Node;
9use crate::graph::{Edge, IndexType};
10use crate::serde_utils::CollectSeqWithLength;
11use crate::serde_utils::MappedSequenceVisitor;
12use crate::serde_utils::{FromDeserialized, IntoSerializable};
13use crate::stable_graph::StableGraph;
14use crate::util::rev;
15use crate::visit::NodeIndexable;
16use crate::EdgeType;
17
18use super::super::serialization::{invalid_length_err, invalid_node_err, EdgeProperty};
19
20// Serialization representation for StableGraph
21// Keep in sync with deserialization and Graph
22#[derive(Serialize)]
23#[serde(rename = "Graph")]
24#[serde(bound(serialize = "N: Serialize, E: Serialize, Ix: IndexType + Serialize"))]
25pub struct SerStableGraph<'a, N: 'a, E: 'a, Ix: 'a + IndexType> {
26    nodes: Somes<&'a [Node<Option<N>, Ix>]>,
27    node_holes: Holes<&'a [Node<Option<N>, Ix>]>,
28    edge_property: EdgeProperty,
29    #[serde(serialize_with = "ser_stable_graph_edges")]
30    edges: &'a [Edge<Option<E>, Ix>],
31}
32
33// Deserialization representation for StableGraph
34// Keep in sync with serialization and Graph
35#[derive(Deserialize)]
36#[serde(rename = "Graph")]
37#[serde(bound(
38    deserialize = "N: Deserialize<'de>, E: Deserialize<'de>, Ix: IndexType + Deserialize<'de>"
39))]
40pub struct DeserStableGraph<N, E, Ix> {
41    #[serde(deserialize_with = "deser_stable_graph_nodes")]
42    nodes: Vec<Node<Option<N>, Ix>>,
43    #[serde(default = "Vec::new")]
44    node_holes: Vec<NodeIndex<Ix>>,
45    edge_property: EdgeProperty,
46    #[serde(deserialize_with = "deser_stable_graph_edges")]
47    edges: Vec<Edge<Option<E>, Ix>>,
48}
49
50/// `Somes` are the present node weights N, with known length.
51struct Somes<T>(usize, T);
52
53impl<'a, N, Ix> Serialize for Somes<&'a [Node<Option<N>, Ix>]>
54where
55    N: Serialize,
56{
57    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
58    where
59        S: Serializer,
60    {
61        serializer.collect_seq_with_length(
62            self.0,
63            self.1.iter().filter_map(|node| node.weight.as_ref()),
64        )
65    }
66}
67
68/// Holes are the node indices of vacancies, with known length
69struct Holes<T>(usize, T);
70
71impl<'a, N, Ix> Serialize for Holes<&'a [Node<Option<N>, Ix>]>
72where
73    Ix: Serialize + IndexType,
74{
75    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
76    where
77        S: Serializer,
78    {
79        serializer.collect_seq_with_length(
80            self.0,
81            self.1.iter().enumerate().filter_map(|(i, node)| {
82                if node.weight.is_none() {
83                    Some(NodeIndex::<Ix>::new(i))
84                } else {
85                    None
86                }
87            }),
88        )
89    }
90}
91
92fn ser_stable_graph_edges<S, E, Ix>(
93    edges: &&[Edge<Option<E>, Ix>],
94    serializer: S,
95) -> Result<S::Ok, S::Error>
96where
97    S: Serializer,
98    E: Serialize,
99    Ix: Serialize + IndexType,
100{
101    serializer.collect_seq_exact(edges.iter().map(|edge| {
102        edge.weight
103            .as_ref()
104            .map(|w| (edge.source(), edge.target(), w))
105    }))
106}
107
108fn deser_stable_graph_nodes<'de, D, N, Ix>(
109    deserializer: D,
110) -> Result<Vec<Node<Option<N>, Ix>>, D::Error>
111where
112    D: Deserializer<'de>,
113    N: Deserialize<'de>,
114    Ix: IndexType + Deserialize<'de>,
115{
116    deserializer.deserialize_seq(MappedSequenceVisitor::new(|n| {
117        Ok(Node {
118            weight: Some(n),
119            next: [EdgeIndex::end(); 2],
120        })
121    }))
122}
123
124fn deser_stable_graph_edges<'de, D, N, Ix>(
125    deserializer: D,
126) -> Result<Vec<Edge<Option<N>, Ix>>, D::Error>
127where
128    D: Deserializer<'de>,
129    N: Deserialize<'de>,
130    Ix: IndexType + Deserialize<'de>,
131{
132    deserializer.deserialize_seq(MappedSequenceVisitor::<
133        Option<(NodeIndex<Ix>, NodeIndex<Ix>, N)>,
134        _,
135        _,
136    >::new(|x| {
137        if let Some((i, j, w)) = x {
138            Ok(Edge {
139                weight: Some(w),
140                node: [i, j],
141                next: [EdgeIndex::end(); 2],
142            })
143        } else {
144            Ok(Edge {
145                weight: None,
146                node: [NodeIndex::end(); 2],
147                next: [EdgeIndex::end(); 2],
148            })
149        }
150    }))
151}
152
153impl<'a, N, E, Ty, Ix> IntoSerializable for &'a StableGraph<N, E, Ty, Ix>
154where
155    Ix: IndexType,
156    Ty: EdgeType,
157{
158    type Output = SerStableGraph<'a, N, E, Ix>;
159    fn into_serializable(self) -> Self::Output {
160        let nodes = &self.raw_nodes()[..self.node_bound()];
161        let node_count = self.node_count();
162        let hole_count = nodes.len() - node_count;
163        let edges = &self.raw_edges()[..self.edge_bound()];
164        SerStableGraph {
165            nodes: Somes(node_count, nodes),
166            node_holes: Holes(hole_count, nodes),
167            edges: edges,
168            edge_property: EdgeProperty::from(PhantomData::<Ty>),
169        }
170    }
171}
172
173/// Requires crate feature `"serde-1"`
174impl<N, E, Ty, Ix> Serialize for StableGraph<N, E, Ty, Ix>
175where
176    Ty: EdgeType,
177    Ix: IndexType + Serialize,
178    N: Serialize,
179    E: Serialize,
180{
181    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
182    where
183        S: Serializer,
184    {
185        self.into_serializable().serialize(serializer)
186    }
187}
188
189impl<'a, N, E, Ty, Ix> FromDeserialized for StableGraph<N, E, Ty, Ix>
190where
191    Ix: IndexType,
192    Ty: EdgeType,
193{
194    type Input = DeserStableGraph<N, E, Ix>;
195    fn from_deserialized<E2>(input: Self::Input) -> Result<Self, E2>
196    where
197        E2: Error,
198    {
199        let ty = PhantomData::<Ty>::from_deserialized(input.edge_property)?;
200        let mut nodes = input.nodes;
201        let node_holes = input.node_holes;
202        let edges = input.edges;
203        if edges.len() >= <Ix as IndexType>::max().index() {
204            Err(invalid_length_err::<Ix, _>("edge", edges.len()))?
205        }
206
207        // insert Nones for each hole
208        let mut offset = node_holes.len();
209        let node_bound = node_holes.len() + nodes.len();
210        for hole_pos in rev(node_holes) {
211            offset -= 1;
212            if hole_pos.index() >= node_bound {
213                Err(invalid_node_err(hole_pos.index(), node_bound))?;
214            }
215            let insert_pos = hole_pos.index() - offset;
216            nodes.insert(
217                insert_pos,
218                Node {
219                    weight: None,
220                    next: [EdgeIndex::end(); 2],
221                },
222            );
223        }
224
225        if nodes.len() >= <Ix as IndexType>::max().index() {
226            Err(invalid_length_err::<Ix, _>("node", nodes.len()))?
227        }
228
229        let node_bound = nodes.len();
230        let mut sgr = StableGraph {
231            g: Graph {
232                nodes: nodes,
233                edges: edges,
234                ty: ty,
235            },
236            node_count: 0,
237            edge_count: 0,
238            free_edge: EdgeIndex::end(),
239            free_node: NodeIndex::end(),
240        };
241        sgr.link_edges()
242            .map_err(|i| invalid_node_err(i.index(), node_bound))?;
243        Ok(sgr)
244    }
245}
246
247/// Requires crate feature `"serde-1"`
248impl<'de, N, E, Ty, Ix> Deserialize<'de> for StableGraph<N, E, Ty, Ix>
249where
250    Ty: EdgeType,
251    Ix: IndexType + Deserialize<'de>,
252    N: Deserialize<'de>,
253    E: Deserialize<'de>,
254{
255    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
256    where
257        D: Deserializer<'de>,
258    {
259        Self::from_deserialized(DeserStableGraph::deserialize(deserializer)?)
260    }
261}
262
263#[test]
264fn test_from_deserialized_with_holes() {
265    use crate::graph::node_index;
266    use crate::stable_graph::StableUnGraph;
267    use itertools::assert_equal;
268    use serde::de::value::Error as SerdeError;
269
270    let input = DeserStableGraph::<_, (), u32> {
271        nodes: vec![
272            Node {
273                weight: Some(1),
274                next: [EdgeIndex::end(); 2],
275            },
276            Node {
277                weight: Some(4),
278                next: [EdgeIndex::end(); 2],
279            },
280            Node {
281                weight: Some(5),
282                next: [EdgeIndex::end(); 2],
283            },
284        ],
285        node_holes: vec![node_index(0), node_index(2), node_index(3), node_index(6)],
286        edges: vec![],
287        edge_property: EdgeProperty::Undirected,
288    };
289    let graph = StableUnGraph::from_deserialized::<SerdeError>(input).unwrap();
290
291    assert_eq!(graph.node_count(), 3);
292    assert_equal(
293        graph.raw_nodes().iter().map(|n| n.weight.as_ref().cloned()),
294        vec![None, Some(1), None, None, Some(4), Some(5), None],
295    );
296}