1use crate::diff::{EdgeDiff, GraphDiff, NodeDiff};
2use hashbrown::{HashMap, HashSet};
3use serde::{Deserialize, Serialize};
4use std::{hash::Hash, ops::AddAssign};
5
6type SlimDiff<Id> = (
11 HashMap<Id, String>, HashSet<Id>, EdgeDiff<Id>, );
15
16pub fn graph_diff_to_bytes<Id, T>(
18 diff: &GraphDiff<Id, T>,
19) -> Result<Vec<u8>, Box<dyn std::error::Error>>
20where
21 Id: Copy + Eq + Hash + Serialize,
22 T: AddAssign + Default + Serialize,
23{
24 let mut json_map: HashMap<Id, String> = HashMap::new();
26 for (k, v) in diff.new_or_updated_nodes() {
27 let json_str = serde_json::to_string(v)?;
28 json_map.insert(*k, json_str);
29 }
30 Ok(bincode::serialize(&(
31 json_map,
32 diff.deleted_nodes(),
33 diff.edges(),
34 ))?)
35}
36
37pub fn bytes_to_graph_diff<Id, T>(
39 bytes: &[u8],
40) -> Result<GraphDiff<Id, T>, Box<dyn std::error::Error>>
41where
42 Id: Copy + Eq + Hash + for<'de> Deserialize<'de>,
43 for<'a> T: AddAssign + Default + Deserialize<'a> + Serialize,
44{
45 let deserialized: SlimDiff<Id> = bincode::deserialize(bytes)?;
46 let mut new_or_updated: HashMap<Id, T> = HashMap::new();
47 for (id, json) in deserialized.0 {
48 new_or_updated.insert(id, serde_json::from_str::<T>(&json)?);
49 }
50 Ok(GraphDiff {
51 nodes: NodeDiff::new(new_or_updated, deserialized.1),
52 edges: deserialized.2,
53 })
54}
55
56#[cfg(test)]
57mod tests {
58
59 use super::*;
60 use crate::{diff::GraphDiff, node_update::NodeUpdate};
61
62 #[test]
63 fn test_serialization() {
64 let mut diff = GraphDiff::<usize, NodeUpdate>::new();
65 diff.add_or_update_node(&1, NodeUpdate::default());
66 diff.add_or_update_node(
67 &2,
68 NodeUpdate {
69 label: Some("test".to_string()),
70 ..NodeUpdate::default()
71 },
72 );
73 diff.add_or_update_node(
74 &3,
75 NodeUpdate {
76 red: Some(5),
77 ..NodeUpdate::default()
78 },
79 );
80 diff.add_edge(&1, &2, 0.).unwrap();
81 diff.add_edge(&2, &3, 10.).unwrap();
82
83 let bytes = graph_diff_to_bytes(&diff).unwrap();
84 let deserialized = bytes_to_graph_diff::<usize, NodeUpdate>(&bytes).unwrap();
85 assert_eq!(diff, deserialized);
86 }
87}