petgraph/graph_impl/
serialization.rs

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