use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct TreeSnapshot {
pub nodes: Vec<SnapshotNode>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct SnapshotNode {
pub edge: String,
pub tenants: Vec<(String, u64)>,
pub child_count: u32,
}
impl TreeSnapshot {
pub fn empty() -> Self {
Self { nodes: Vec::new() }
}
pub fn to_bytes(&self) -> Result<Vec<u8>, Box<bincode::ErrorKind>> {
bincode::serialize(self)
}
pub fn from_bytes(bytes: &[u8]) -> Result<Self, Box<bincode::ErrorKind>> {
bincode::deserialize(bytes)
}
pub fn node_count(&self) -> usize {
self.nodes.len()
}
pub fn total_edge_bytes(&self) -> usize {
self.nodes.iter().map(|n| n.edge.len()).sum()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_snapshot_round_trip() {
let snapshot = TreeSnapshot {
nodes: vec![
SnapshotNode {
edge: String::new(),
tenants: vec![("worker-1".to_string(), 100)],
child_count: 2,
},
SnapshotNode {
edge: "Hello ".to_string(),
tenants: vec![("worker-1".to_string(), 100)],
child_count: 1,
},
SnapshotNode {
edge: "world".to_string(),
tenants: vec![("worker-1".to_string(), 100)],
child_count: 0,
},
SnapshotNode {
edge: "Goodbye".to_string(),
tenants: vec![("worker-2".to_string(), 200)],
child_count: 0,
},
],
};
let bytes = snapshot.to_bytes().unwrap();
let restored = TreeSnapshot::from_bytes(&bytes).unwrap();
assert_eq!(snapshot, restored);
}
#[test]
fn test_empty_snapshot() {
let snapshot = TreeSnapshot::empty();
assert_eq!(snapshot.node_count(), 0);
assert_eq!(snapshot.total_edge_bytes(), 0);
let bytes = snapshot.to_bytes().unwrap();
let restored = TreeSnapshot::from_bytes(&bytes).unwrap();
assert_eq!(snapshot, restored);
}
}