petgraph/graph_impl/
serialization.rs

1use serde::de::Error;
2
3#[cfg(not(feature = "std"))]
4use core::marker::PhantomData;
5#[cfg(feature = "std")]
6use std::marker::PhantomData;
7
8#[cfg(not(feature = "std"))]
9use alloc::vec::Vec;
10
11use crate::prelude::*;
12
13use crate::graph::Node;
14use crate::graph::{Edge, IndexType};
15use crate::serde_utils::CollectSeqWithLength;
16use crate::serde_utils::MappedSequenceVisitor;
17use crate::serde_utils::{FromDeserialized, IntoSerializable};
18use crate::EdgeType;
19
20use super::{EdgeIndex, NodeIndex};
21use serde::{Deserialize, Deserializer, Serialize, Serializer};
22
23/// Serialization representation for Graph
24/// Keep in sync with deserialization and StableGraph
25///
26/// The serialization format is as follows, in Pseudorust:
27///
28/// Graph {
29///     nodes: [N],
30///     node_holes: [NodeIndex<Ix>],
31///     edge_property: EdgeProperty,
32///     edges: [Option<(NodeIndex<Ix>, NodeIndex<Ix>, E)>]
33/// }
34///
35/// The same format is used by both Graph and StableGraph.
36///
37/// For graph there are restrictions:
38/// node_holes is always empty and edges are always Some
39///
40/// A stable graph serialization that obeys these restrictions
41/// (effectively, it has no interior vacancies) can de deserialized
42/// as a graph.
43///
44/// Node indices are serialized as integers and are fixed size for
45/// binary formats, so the Ix parameter matters there.
46#[derive(Serialize)]
47#[serde(rename = "Graph")]
48#[serde(bound(serialize = "N: Serialize, E: Serialize, Ix: IndexType + Serialize"))]
49pub struct SerGraph<'a, N: 'a, E: 'a, Ix: 'a + IndexType> {
50    #[serde(serialize_with = "ser_graph_nodes")]
51    nodes: &'a [Node<N, Ix>],
52    node_holes: &'a [NodeIndex<Ix>],
53    edge_property: EdgeProperty,
54    #[serde(serialize_with = "ser_graph_edges")]
55    edges: &'a [Edge<E, Ix>],
56}
57
58// Deserialization representation for Graph
59// Keep in sync with serialization and StableGraph
60#[derive(Deserialize)]
61#[serde(rename = "Graph")]
62#[serde(bound(
63    deserialize = "N: Deserialize<'de>, E: Deserialize<'de>, Ix: IndexType + Deserialize<'de>"
64))]
65pub struct DeserGraph<N, E, Ix> {
66    #[serde(deserialize_with = "deser_graph_nodes")]
67    nodes: Vec<Node<N, Ix>>,
68    #[serde(deserialize_with = "deser_graph_node_holes")]
69    #[allow(unused)]
70    #[serde(default = "Vec::new")]
71    node_holes: Vec<NodeIndex<Ix>>,
72    edge_property: EdgeProperty,
73    #[serde(deserialize_with = "deser_graph_edges")]
74    edges: Vec<Edge<E, Ix>>,
75}
76
77impl<Ix> Serialize for NodeIndex<Ix>
78where
79    Ix: IndexType + Serialize,
80{
81    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
82    where
83        S: Serializer,
84    {
85        self.0.serialize(serializer)
86    }
87}
88
89impl<'de, Ix> Deserialize<'de> for NodeIndex<Ix>
90where
91    Ix: IndexType + Deserialize<'de>,
92{
93    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
94    where
95        D: Deserializer<'de>,
96    {
97        Ok(NodeIndex(Ix::deserialize(deserializer)?))
98    }
99}
100
101impl<Ix> Serialize for EdgeIndex<Ix>
102where
103    Ix: IndexType + Serialize,
104{
105    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
106    where
107        S: Serializer,
108    {
109        self.0.serialize(serializer)
110    }
111}
112
113impl<'de, Ix> Deserialize<'de> for EdgeIndex<Ix>
114where
115    Ix: IndexType + Deserialize<'de>,
116{
117    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
118    where
119        D: Deserializer<'de>,
120    {
121        Ok(EdgeIndex(Ix::deserialize(deserializer)?))
122    }
123}
124
125#[derive(Serialize, Deserialize)]
126#[serde(rename_all = "lowercase")]
127#[derive(Debug)]
128pub enum EdgeProperty {
129    Undirected,
130    Directed,
131}
132
133impl EdgeProperty {
134    pub fn is_directed(&self) -> bool {
135        match *self {
136            EdgeProperty::Directed => true,
137            EdgeProperty::Undirected => false,
138        }
139    }
140}
141
142impl<Ty> From<PhantomData<Ty>> for EdgeProperty
143where
144    Ty: EdgeType,
145{
146    fn from(_: PhantomData<Ty>) -> Self {
147        if Ty::is_directed() {
148            EdgeProperty::Directed
149        } else {
150            EdgeProperty::Undirected
151        }
152    }
153}
154
155impl<Ty> FromDeserialized for PhantomData<Ty>
156where
157    Ty: EdgeType,
158{
159    type Input = EdgeProperty;
160    fn from_deserialized<E2>(input: Self::Input) -> Result<Self, E2>
161    where
162        E2: Error,
163    {
164        if input.is_directed() != Ty::is_directed() {
165            Err(E2::custom(format_args!(
166                "graph edge property mismatch, \
167                 expected {:?}, found {:?}",
168                EdgeProperty::from(PhantomData::<Ty>),
169                input
170            )))
171        } else {
172            Ok(PhantomData)
173        }
174    }
175}
176
177fn ser_graph_nodes<S, N, Ix>(nodes: &&[Node<N, Ix>], serializer: S) -> Result<S::Ok, S::Error>
178where
179    S: Serializer,
180    N: Serialize,
181    Ix: Serialize + IndexType,
182{
183    serializer.collect_seq_exact(nodes.iter().map(|node| &node.weight))
184}
185
186fn ser_graph_edges<S, E, Ix>(edges: &&[Edge<E, Ix>], serializer: S) -> Result<S::Ok, S::Error>
187where
188    S: Serializer,
189    E: Serialize,
190    Ix: Serialize + IndexType,
191{
192    serializer.collect_seq_exact(
193        edges
194            .iter()
195            .map(|edge| Some((edge.source(), edge.target(), &edge.weight))),
196    )
197}
198
199fn deser_graph_nodes<'de, D, N, Ix>(deserializer: D) -> Result<Vec<Node<N, Ix>>, D::Error>
200where
201    D: Deserializer<'de>,
202    N: Deserialize<'de>,
203    Ix: IndexType + Deserialize<'de>,
204{
205    deserializer.deserialize_seq(MappedSequenceVisitor::new(|n| {
206        Ok(Node {
207            weight: n,
208            next: [EdgeIndex::end(); 2],
209        })
210    }))
211}
212
213fn deser_graph_node_holes<'de, D, Ix>(deserializer: D) -> Result<Vec<NodeIndex<Ix>>, D::Error>
214where
215    D: Deserializer<'de>,
216    Ix: IndexType + Deserialize<'de>,
217{
218    deserializer.deserialize_seq(
219        MappedSequenceVisitor::<NodeIndex<Ix>, NodeIndex<Ix>, _>::new(|_| {
220            Err("Graph can not have holes in the node set, found non-empty node_holes")
221        }),
222    )
223}
224
225fn deser_graph_edges<'de, D, N, Ix>(deserializer: D) -> Result<Vec<Edge<N, Ix>>, D::Error>
226where
227    D: Deserializer<'de>,
228    N: Deserialize<'de>,
229    Ix: IndexType + Deserialize<'de>,
230{
231    deserializer.deserialize_seq(MappedSequenceVisitor::<
232        Option<(NodeIndex<Ix>, NodeIndex<Ix>, N)>,
233        _,
234        _,
235    >::new(|x| {
236        if let Some((i, j, w)) = x {
237            Ok(Edge {
238                weight: w,
239                node: [i, j],
240                next: [EdgeIndex::end(); 2],
241            })
242        } else {
243            Err("Graph can not have holes in the edge set, found None, expected edge")
244        }
245    }))
246}
247
248impl<'a, N, E, Ty, Ix> IntoSerializable for &'a Graph<N, E, Ty, Ix>
249where
250    Ix: IndexType,
251    Ty: EdgeType,
252{
253    type Output = SerGraph<'a, N, E, Ix>;
254    fn into_serializable(self) -> Self::Output {
255        SerGraph {
256            nodes: &self.nodes,
257            node_holes: &[],
258            edges: &self.edges,
259            edge_property: EdgeProperty::from(PhantomData::<Ty>),
260        }
261    }
262}
263
264/// Requires crate feature `"serde-1"`
265impl<N, E, Ty, Ix> Serialize for Graph<N, E, Ty, Ix>
266where
267    Ty: EdgeType,
268    Ix: IndexType + Serialize,
269    N: Serialize,
270    E: Serialize,
271{
272    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
273    where
274        S: Serializer,
275    {
276        self.into_serializable().serialize(serializer)
277    }
278}
279
280pub fn invalid_node_err<E>(node_index: usize, len: usize) -> E
281where
282    E: Error,
283{
284    E::custom(format_args!(
285        "invalid value: node index `{}` does not exist in graph \
286         with node bound {}",
287        node_index, len
288    ))
289}
290
291pub fn invalid_length_err<Ix, E>(node_or_edge: &str, len: usize) -> E
292where
293    E: Error,
294    Ix: IndexType,
295{
296    E::custom(format_args!(
297        "invalid size: graph {} count {} exceeds index type maximum {}",
298        node_or_edge,
299        len,
300        <Ix as IndexType>::max().index()
301    ))
302}
303
304impl<'a, N, E, Ty, Ix> FromDeserialized for Graph<N, E, Ty, Ix>
305where
306    Ix: IndexType,
307    Ty: EdgeType,
308{
309    type Input = DeserGraph<N, E, Ix>;
310    fn from_deserialized<E2>(input: Self::Input) -> Result<Self, E2>
311    where
312        E2: Error,
313    {
314        let ty = PhantomData::<Ty>::from_deserialized(input.edge_property)?;
315        let nodes = input.nodes;
316        let edges = input.edges;
317        if nodes.len() >= <Ix as IndexType>::max().index() {
318            Err(invalid_length_err::<Ix, _>("node", nodes.len()))?
319        }
320
321        if edges.len() >= <Ix as IndexType>::max().index() {
322            Err(invalid_length_err::<Ix, _>("edge", edges.len()))?
323        }
324
325        let mut gr = Graph {
326            nodes: nodes,
327            edges: edges,
328            ty: ty,
329        };
330        let nc = gr.node_count();
331        gr.link_edges()
332            .map_err(|i| invalid_node_err(i.index(), nc))?;
333        Ok(gr)
334    }
335}
336
337/// Requires crate feature `"serde-1"`
338impl<'de, N, E, Ty, Ix> Deserialize<'de> for Graph<N, E, Ty, Ix>
339where
340    Ty: EdgeType,
341    Ix: IndexType + Deserialize<'de>,
342    N: Deserialize<'de>,
343    E: Deserialize<'de>,
344{
345    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
346    where
347        D: Deserializer<'de>,
348    {
349        Self::from_deserialized(DeserGraph::deserialize(deserializer)?)
350    }
351}