drisk_api/
bytes.rs

1use crate::diff::{EdgeDiff, GraphDiff, NodeDiff};
2use hashbrown::{HashMap, HashSet};
3use serde::{Deserialize, Serialize};
4use std::{hash::Hash, ops::AddAssign};
5
6/*
7 * GraphDiff (de-)serialization
8 */
9
10type SlimDiff<Id> = (
11    HashMap<Id, String>, // JSON new node properties (serde field skip)
12    HashSet<Id>,         // deleted node ids
13    EdgeDiff<Id>,        // EdgeDiff
14);
15
16/// Serialize a `GraphDiff` to a byte vector.
17pub 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    // make use of serde skip fields
25    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
37/// Deserialize a `GraphDiff` from a byte slice.
38pub 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}