use crate::digest::ValueDigest;
use crate::node::ProllyNode;
use std::fs::{self, File};
use std::io::{Read, Write};
use std::path::PathBuf;
use std::sync::Arc;
use super::{NodeStorage, StorageError};
#[derive(Clone, Debug)]
pub struct FileNodeStorage<const N: usize> {
storage_dir: PathBuf,
}
impl<const N: usize> FileNodeStorage<N> {
pub fn new(storage_dir: PathBuf) -> Result<Self, StorageError> {
fs::create_dir_all(&storage_dir)?;
Ok(FileNodeStorage { storage_dir })
}
fn node_path(&self, hash: &ValueDigest<N>) -> PathBuf {
self.storage_dir.join(format!("{hash:x}"))
}
fn config_path(&self, key: &str) -> PathBuf {
self.storage_dir.join(format!("config_{key}"))
}
}
impl<const N: usize> NodeStorage<N> for FileNodeStorage<N> {
fn get_node_by_hash(&self, hash: &ValueDigest<N>) -> Option<Arc<ProllyNode<N>>> {
let path = self.node_path(hash);
if path.exists() {
let mut file = File::open(path).ok()?;
let mut data = Vec::new();
file.read_to_end(&mut data).ok()?;
let node: ProllyNode<N> = bincode::deserialize(&data).ok()?;
Some(Arc::new(node))
} else {
None
}
}
fn insert_node(
&mut self,
hash: ValueDigest<N>,
node: ProllyNode<N>,
) -> Result<(), StorageError> {
let path = self.node_path(&hash);
let data = bincode::serialize(&node)?;
let mut file = File::create(path)?;
file.write_all(&data)?;
Ok(())
}
fn delete_node(&mut self, hash: &ValueDigest<N>) -> Result<(), StorageError> {
let path = self.node_path(hash);
if path.exists() {
fs::remove_file(path)?;
}
Ok(())
}
fn save_config(&self, key: &str, config: &[u8]) {
let path = self.config_path(key);
if let Ok(mut file) = File::create(path) {
let _ = file.write_all(config);
}
}
fn get_config(&self, key: &str) -> Option<Vec<u8>> {
let path = self.config_path(key);
if path.exists() {
let mut file = File::open(path).ok()?;
let mut data = Vec::new();
file.read_to_end(&mut data).ok()?;
Some(data)
} else {
None
}
}
}