threatflux_cache/
storage.rs1use crate::entry::CacheEntry;
4use crate::error::Result;
5use async_trait::async_trait;
6use serde::{de::DeserializeOwned, Serialize};
7use std::collections::HashMap;
8use std::hash::Hash;
9
10#[async_trait]
12pub trait StorageBackend: Send + Sync + 'static {
13 type Key: Serialize + DeserializeOwned + Hash + Eq + Clone + Send + Sync;
15 type Value: Serialize + DeserializeOwned + Clone + Send + Sync;
17 type Metadata: Serialize + DeserializeOwned + Clone + Send + Sync;
19
20 async fn save(
22 &self,
23 entries: &HashMap<Self::Key, Vec<CacheEntry<Self::Key, Self::Value, Self::Metadata>>>,
24 ) -> Result<()>;
25
26 async fn load(
28 &self,
29 ) -> Result<HashMap<Self::Key, Vec<CacheEntry<Self::Key, Self::Value, Self::Metadata>>>>;
30
31 async fn remove(&self, key: &Self::Key) -> Result<()>;
33
34 async fn clear(&self) -> Result<()>;
36
37 async fn contains(&self, key: &Self::Key) -> Result<bool> {
39 let entries = self.load().await?;
40 Ok(entries.contains_key(key))
41 }
42
43 async fn size_bytes(&self) -> Result<u64> {
45 Ok(0) }
47
48 async fn compact(&self) -> Result<()> {
50 Ok(()) }
52}
53
54#[derive(Debug, Clone, Copy, PartialEq, Eq)]
56pub enum SerializationFormat {
57 #[cfg(feature = "json-serialization")]
59 Json,
60 #[cfg(feature = "bincode-serialization")]
62 Bincode,
63}
64
65impl SerializationFormat {
66 pub fn extension(&self) -> &'static str {
68 match self {
69 #[cfg(feature = "json-serialization")]
70 SerializationFormat::Json => "json",
71 #[cfg(feature = "bincode-serialization")]
72 SerializationFormat::Bincode => "bin",
73 #[cfg(not(any(feature = "json-serialization", feature = "bincode-serialization")))]
74 _ => "data",
75 }
76 }
77
78 #[allow(unused_variables)]
80 pub fn serialize<T: Serialize>(&self, value: &T) -> Result<Vec<u8>> {
81 match self {
82 #[cfg(feature = "json-serialization")]
83 SerializationFormat::Json => serde_json::to_vec_pretty(value).map_err(Into::into),
84 #[cfg(feature = "bincode-serialization")]
85 SerializationFormat::Bincode => bincode::serialize(value).map_err(Into::into),
86 #[cfg(not(any(feature = "json-serialization", feature = "bincode-serialization")))]
87 _ => Err(crate::error::CacheError::Serialization(
88 "No serialization features enabled".to_string(),
89 )),
90 }
91 }
92
93 #[allow(unused_variables)]
95 pub fn deserialize<T: DeserializeOwned>(&self, data: &[u8]) -> Result<T> {
96 match self {
97 #[cfg(feature = "json-serialization")]
98 SerializationFormat::Json => serde_json::from_slice(data).map_err(Into::into),
99 #[cfg(feature = "bincode-serialization")]
100 SerializationFormat::Bincode => bincode::deserialize(data).map_err(Into::into),
101 #[cfg(not(any(feature = "json-serialization", feature = "bincode-serialization")))]
102 _ => Err(crate::error::CacheError::Serialization(
103 "No serialization features enabled".to_string(),
104 )),
105 }
106 }
107}
108
109#[derive(Debug, Clone, Default)]
111pub struct StorageStats {
112 pub total_keys: usize,
114 pub total_entries: usize,
116 pub total_bytes: u64,
118 pub avg_entries_per_key: f64,
120}
121
122#[cfg(test)]
123mod tests {
124 #[cfg(any(feature = "json-serialization", feature = "bincode-serialization"))]
125 use super::*;
126
127 #[test]
128 fn test_serialization_format_extension() {
129 #[cfg(feature = "json-serialization")]
130 assert_eq!(SerializationFormat::Json.extension(), "json");
131
132 #[cfg(feature = "bincode-serialization")]
133 assert_eq!(SerializationFormat::Bincode.extension(), "bin");
134 }
135
136 #[cfg(feature = "json-serialization")]
137 #[test]
138 fn test_json_serialization() {
139 use serde::{Deserialize, Serialize};
140
141 #[derive(Serialize, Deserialize, PartialEq, Debug)]
142 struct TestData {
143 value: String,
144 }
145
146 let data = TestData {
147 value: "test".to_string(),
148 };
149 let format = SerializationFormat::Json;
150
151 let serialized = format.serialize(&data).unwrap();
152 let deserialized: TestData = format.deserialize(&serialized).unwrap();
153
154 assert_eq!(data, deserialized);
155 }
156}