1use crate::asyncronous::encryption::{
2 database_aes_decrypt as sym_aes_decrypt, database_aes_encrypt as sym_aes_encrypt,
3};
4use crate::error::NetworkError;
5use serde::{de::DeserializeOwned, Serialize};
6use std::collections::hash_map::{IntoIter, Iter, IterMut};
7use std::collections::HashMap;
8use std::fmt;
9use std::iter::IntoIterator;
10use std::path::Path;
11use std::path::PathBuf;
12
13use std::fs::File;
14use std::io::{Read, Write};
15use std::{fmt::Debug, hash::Hash};
16use tar::{Archive, Builder};
17use walkdir::WalkDir;
18
19pub trait HashValue: 'static + Debug + Serialize + DeserializeOwned + Clone + Send + Sync {}
21pub trait HashKey: 'static + Hash + ToString + PartialEq + Eq + Clone + Send + Sync {}
23impl<V> HashValue for V where V: 'static + Debug + Serialize + DeserializeOwned + Send + Clone + Sync
24{}
25impl<K> HashKey for K where K: 'static + ToString + Hash + PartialEq + Eq + Clone + Send + Sync {}
26impl<V: HashValue, K: HashKey> Debug for HashDatabase<V, K>
27where
28 K: Debug,
29 V: Debug,
30{
31 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
32 f.debug_struct("Point")
33 .field("data", &self.data)
34 .field("key", &self.key)
35 .field("root", &self.root)
36 .finish()
37 }
38}
39impl<'a, V: HashValue, K: HashKey> IntoIterator for &'a HashDatabase<V, K> {
42 type Item = (&'a K, &'a V);
43 type IntoIter = Iter<'a, K, V>;
44
45 #[inline]
46 fn into_iter(self) -> Iter<'a, K, V> {
47 self.data.iter()
48 }
49}
50impl<V: HashValue, K: HashKey> IntoIterator for HashDatabase<V, K> {
51 type Item = (K, V);
52 type IntoIter = IntoIter<K, V>;
53 fn into_iter(self) -> IntoIter<K, V> {
54 self.data.into_iter()
55 }
56}
57impl<'a, V: HashValue, K: HashKey> IntoIterator for &'a mut HashDatabase<V, K> {
58 type Item = (&'a K, &'a mut V);
59 type IntoIter = IterMut<'a, K, V>;
60
61 #[inline]
62 fn into_iter(self) -> IterMut<'a, K, V> {
63 self.data.iter_mut()
64 }
65}
66#[derive(Clone)]
67pub struct HashDatabase<V: HashValue, K: HashKey = String> {
68 data: HashMap<K, V>,
69 key: Vec<u8>,
70 root: PathBuf,
71}
72impl<V: HashValue, K: HashKey> HashDatabase<V, K> {
73 pub fn new<P: AsRef<Path>>(path: P, key: Vec<u8>) -> Result<Self, NetworkError> {
78 let root = path.as_ref().to_path_buf();
79 if !root.exists() {
80 std::fs::create_dir(root.clone())?;
81 }
82 Ok(Self {
83 data: HashMap::new(),
84 key,
85 root,
86 })
87 }
88 pub fn insert(&mut self, key: K, item: V) -> Result<(), NetworkError> {
89 self.data.insert(key.clone(), item.clone());
90 let path_str = key.to_string();
91 let path = self.root.join(path_str);
92 let mut file = File::create(path)?;
93 let mut data = serde_json::to_string(&item)?.into_bytes();
94 sym_aes_encrypt(&self.key, &mut data);
95 Ok(file.write_all(&data)?)
96 }
97 pub fn get(&self, key: &K) -> Option<&V> {
98 self.data.get(key)
99 }
100 pub fn load(&mut self, key: &K) -> Result<(), NetworkError> {
101 let path_str = key.to_string();
102 let path = self.root.join(path_str);
103 if !path.exists() {
104 return Err(NetworkError::IOError(std::io::Error::new(
105 std::io::ErrorKind::NotFound,
106 "entry not found",
107 )));
108 }
109 let mut file = File::open(path)?;
110 let mut invec = Vec::new();
111 file.read_to_end(&mut invec)?;
112 sym_aes_decrypt(&self.key, &mut invec);
113 let entry = serde_json::from_str(&String::from_utf8(invec)?)?;
114 self.data.insert(key.clone(), entry);
115 Ok(())
116 }
117 pub fn decompose(self) -> (HashMap<K, V>, PathBuf) {
118 (self.data, self.root)
119 }
120 pub fn index_entries(&self) -> Result<Vec<PathBuf>, NetworkError> {
123 let results: Vec<Result<PathBuf, NetworkError>> = WalkDir::new(self.root.clone())
124 .into_iter()
125 .map(|p| Ok(p?.path().to_path_buf()))
126 .collect();
127 let mut paths = Vec::with_capacity(results.len());
128 for result in results.into_iter() {
129 let path = result?;
130 if path.is_file() {
131 paths.push(path);
132 }
133 }
134 Ok(paths)
135 }
136 pub fn index_subdatabases(&self) -> Result<Vec<PathBuf>, NetworkError> {
138 let results: Vec<Result<PathBuf, NetworkError>> = WalkDir::new(self.root.clone())
139 .into_iter()
140 .map(|p| Ok(p?.path().to_path_buf()))
141 .collect();
142 let mut paths = Vec::with_capacity(results.len());
143 for result in results.into_iter() {
144 let path = result?;
145 if path.is_dir() {
146 paths.push(path);
147 }
148 }
149 Ok(paths)
150 }
151 pub fn read_entry<EV: HashValue>(&self, key: &K) -> Result<EV, NetworkError> {
154 let path_str = key.to_string();
155 let path = self.root.join(path_str);
156 let mut file = File::open(path)?;
157 let mut invec = Vec::new();
158 file.read_to_end(&mut invec)?;
159 sym_aes_decrypt(&self.key, &mut invec);
160 Ok(serde_json::from_str(&String::from_utf8(invec)?)?)
161 }
162 pub fn write_entry<EV: HashValue>(&self, key: &K, value: &EV) -> Result<(), NetworkError> {
165 let path_str = key.to_string();
166 let path = self.root.join(path_str);
167 let mut file = File::open(path)?;
168 let mut outvec = serde_json::to_string(value)?.into_bytes();
169 sym_aes_encrypt(&self.key, &mut outvec);
170 Ok(file.write_all(&outvec)?)
171 }
172 pub fn archive(&self) -> Result<Vec<u8>, NetworkError> {
174 let archive = Vec::new();
175 let mut builder = Builder::new(archive);
176 let results: Vec<std::io::Result<()>> = WalkDir::new(self.root.clone())
177 .into_iter()
178 .map(|p| p.unwrap().into_path())
179 .filter(|p| p.is_file())
180 .map(|p| builder.append_path(p))
181 .collect();
182 for result in results.into_iter() {
183 result?
184 }
185 Ok(builder.into_inner()?)
186 }
187 pub fn dearchive(&self, archive_data: &[u8]) -> std::io::Result<()> {
189 let mut archive = Archive::new(archive_data);
190 for entry in archive.entries()? {
191 let mut entry = entry?;
192 entry.unpack(self.root.join(entry.path()?))?;
193 }
194 Ok(())
195 }
196}