use serde::de::Error; use serde::{Deserialize, Deserializer, Serialize, Serializer}; use std::marker::PhantomData; use crate::prelude::*; use crate::graph::Node; use crate::graph::{Edge, IndexType}; use crate::serde_utils::CollectSeqWithLength; use crate::serde_utils::MappedSequenceVisitor; use crate::serde_utils::{FromDeserialized, IntoSerializable}; use crate::stable_graph::StableGraph; use crate::util::rev; use crate::visit::NodeIndexable; use crate::EdgeType; use super::super::serialization::{invalid_length_err, invalid_node_err, EdgeProperty}; // Serialization representation for StableGraph // Keep in sync with deserialization and Graph #[derive(Serialize)] #[serde(rename = "Graph")] #[serde(bound(serialize = "N: Serialize, E: Serialize, Ix: IndexType + Serialize"))] pub struct SerStableGraph<'a, N: 'a, E: 'a, Ix: 'a + IndexType> { nodes: Somes<&'a [Node, Ix>]>, node_holes: Holes<&'a [Node, Ix>]>, edge_property: EdgeProperty, #[serde(serialize_with = "ser_stable_graph_edges")] edges: &'a [Edge, Ix>], } // Deserialization representation for StableGraph // Keep in sync with serialization and Graph #[derive(Deserialize)] #[serde(rename = "Graph")] #[serde(bound( deserialize = "N: Deserialize<'de>, E: Deserialize<'de>, Ix: IndexType + Deserialize<'de>" ))] pub struct DeserStableGraph { #[serde(deserialize_with = "deser_stable_graph_nodes")] nodes: Vec, Ix>>, #[serde(default = "Vec::new")] node_holes: Vec>, edge_property: EdgeProperty, #[serde(deserialize_with = "deser_stable_graph_edges")] edges: Vec, Ix>>, } /// `Somes` are the present node weights N, with known length. struct Somes(usize, T); impl<'a, N, Ix> Serialize for Somes<&'a [Node, Ix>]> where N: Serialize, { fn serialize(&self, serializer: S) -> Result where S: Serializer, { serializer.collect_seq_with_length( self.0, self.1.iter().filter_map(|node| node.weight.as_ref()), ) } } /// Holes are the node indices of vacancies, with known length struct Holes(usize, T); impl<'a, N, Ix> Serialize for Holes<&'a [Node, Ix>]> where Ix: Serialize + IndexType, { fn serialize(&self, serializer: S) -> Result where S: Serializer, { serializer.collect_seq_with_length( self.0, self.1.iter().enumerate().filter_map(|(i, node)| { if node.weight.is_none() { Some(NodeIndex::::new(i)) } else { None } }), ) } } fn ser_stable_graph_edges( edges: &&[Edge, Ix>], serializer: S, ) -> Result where S: Serializer, E: Serialize, Ix: Serialize + IndexType, { serializer.collect_seq_exact(edges.iter().map(|edge| { edge.weight .as_ref() .map(|w| (edge.source(), edge.target(), w)) })) } fn deser_stable_graph_nodes<'de, D, N, Ix>( deserializer: D, ) -> Result, Ix>>, D::Error> where D: Deserializer<'de>, N: Deserialize<'de>, Ix: IndexType + Deserialize<'de>, { deserializer.deserialize_seq(MappedSequenceVisitor::new(|n| { Ok(Node { weight: Some(n), next: [EdgeIndex::end(); 2], }) })) } fn deser_stable_graph_edges<'de, D, N, Ix>( deserializer: D, ) -> Result, Ix>>, D::Error> where D: Deserializer<'de>, N: Deserialize<'de>, Ix: IndexType + Deserialize<'de>, { deserializer.deserialize_seq(MappedSequenceVisitor::< Option<(NodeIndex, NodeIndex, N)>, _, _, >::new(|x| { if let Some((i, j, w)) = x { Ok(Edge { weight: Some(w), node: [i, j], next: [EdgeIndex::end(); 2], }) } else { Ok(Edge { weight: None, node: [NodeIndex::end(); 2], next: [EdgeIndex::end(); 2], }) } })) } impl<'a, N, E, Ty, Ix> IntoSerializable for &'a StableGraph where Ix: IndexType, Ty: EdgeType, { type Output = SerStableGraph<'a, N, E, Ix>; fn into_serializable(self) -> Self::Output { let nodes = &self.raw_nodes()[..self.node_bound()]; let node_count = self.node_count(); let hole_count = nodes.len() - node_count; let edges = &self.raw_edges()[..self.edge_bound()]; SerStableGraph { nodes: Somes(node_count, nodes), node_holes: Holes(hole_count, nodes), edges: edges, edge_property: EdgeProperty::from(PhantomData::), } } } /// Requires crate feature `"serde-1"` impl Serialize for StableGraph where Ty: EdgeType, Ix: IndexType + Serialize, N: Serialize, E: Serialize, { fn serialize(&self, serializer: S) -> Result where S: Serializer, { self.into_serializable().serialize(serializer) } } impl<'a, N, E, Ty, Ix> FromDeserialized for StableGraph where Ix: IndexType, Ty: EdgeType, { type Input = DeserStableGraph; fn from_deserialized(input: Self::Input) -> Result where E2: Error, { let ty = PhantomData::::from_deserialized(input.edge_property)?; let mut nodes = input.nodes; let node_holes = input.node_holes; let edges = input.edges; if edges.len() >= ::max().index() { Err(invalid_length_err::("edge", edges.len()))? } // insert Nones for each hole let mut offset = node_holes.len(); let node_bound = node_holes.len() + nodes.len(); for hole_pos in rev(node_holes) { offset -= 1; if hole_pos.index() >= node_bound { Err(invalid_node_err(hole_pos.index(), node_bound))?; } let insert_pos = hole_pos.index() - offset; nodes.insert( insert_pos, Node { weight: None, next: [EdgeIndex::end(); 2], }, ); } if nodes.len() >= ::max().index() { Err(invalid_length_err::("node", nodes.len()))? } let node_bound = nodes.len(); let mut sgr = StableGraph { g: Graph { nodes: nodes, edges: edges, ty: ty, }, node_count: 0, edge_count: 0, free_edge: EdgeIndex::end(), free_node: NodeIndex::end(), }; sgr.link_edges() .map_err(|i| invalid_node_err(i.index(), node_bound))?; Ok(sgr) } } /// Requires crate feature `"serde-1"` impl<'de, N, E, Ty, Ix> Deserialize<'de> for StableGraph where Ty: EdgeType, Ix: IndexType + Deserialize<'de>, N: Deserialize<'de>, E: Deserialize<'de>, { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { Self::from_deserialized(DeserStableGraph::deserialize(deserializer)?) } } #[test] fn test_from_deserialized_with_holes() { use crate::graph::node_index; use crate::stable_graph::StableUnGraph; use itertools::assert_equal; use serde::de::value::Error as SerdeError; let input = DeserStableGraph::<_, (), u32> { nodes: vec![ Node { weight: Some(1), next: [EdgeIndex::end(); 2], }, Node { weight: Some(4), next: [EdgeIndex::end(); 2], }, Node { weight: Some(5), next: [EdgeIndex::end(); 2], }, ], node_holes: vec![node_index(0), node_index(2), node_index(3), node_index(6)], edges: vec![], edge_property: EdgeProperty::Undirected, }; let graph = StableUnGraph::from_deserialized::(input).unwrap(); assert_eq!(graph.node_count(), 3); assert_equal( graph.raw_nodes().iter().map(|n| n.weight.as_ref().cloned()), vec![None, Some(1), None, None, Some(4), Some(5), None], ); }