//! Persistence traits for data and routing table. //! //! The library defines the traits; applications //! implement backends (SQLite, file, etc). use crate::error::Error; use crate::id::NodeId; use std::net::SocketAddr; /// Stored value record for persistence. #[derive(Debug, Clone)] pub struct StoredRecord { pub key: Vec, pub value: Vec, pub target_id: NodeId, pub source: NodeId, pub ttl: u16, pub is_unique: bool, } /// Contact record for routing table persistence. #[derive(Debug, Clone)] pub struct ContactRecord { pub id: NodeId, pub addr: SocketAddr, } /// Trait for persisting DHT stored values. /// /// Implement this to survive restarts. The library /// calls `save` periodically and `load` on startup. pub trait DataPersistence { /// Save all stored values. fn save(&self, records: &[StoredRecord]) -> Result<(), Error>; /// Load previously saved values. fn load(&self) -> Result, Error>; } /// Trait for persisting the routing table. /// /// Implement this for fast re-bootstrap after restart. pub trait RoutingPersistence { /// Save known contacts. fn save_contacts(&self, contacts: &[ContactRecord]) -> Result<(), Error>; /// Load previously saved contacts. fn load_contacts(&self) -> Result, Error>; } /// No-op persistence (default — no persistence). pub struct NoPersistence; impl DataPersistence for NoPersistence { fn save(&self, _records: &[StoredRecord]) -> Result<(), Error> { Ok(()) } fn load(&self) -> Result, Error> { Ok(Vec::new()) } } impl RoutingPersistence for NoPersistence { fn save_contacts(&self, _contacts: &[ContactRecord]) -> Result<(), Error> { Ok(()) } fn load_contacts(&self) -> Result, Error> { Ok(Vec::new()) } } #[cfg(test)] mod tests { use super::*; #[test] fn no_persistence_save_load() { let p = NoPersistence; assert!(p.save(&[]).is_ok()); assert!(p.load().unwrap().is_empty()); assert!(p.save_contacts(&[]).is_ok()); assert!(p.load_contacts().unwrap().is_empty()); } }