petgraph/graph_impl/stable_graph/
serialization.rs

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