1use std::hash::{BuildHasher, BuildHasherDefault, Hash};
16
17use twox_hash::XxHash64;
18
19pub trait Key: Send + Sync + 'static + Hash + Eq {}
21pub trait Value: Send + Sync + 'static {}
23
24impl<T: Send + Sync + 'static + std::hash::Hash + Eq> Key for T {}
25impl<T: Send + Sync + 'static> Value for T {}
26
27pub trait HashBuilder: BuildHasher + Send + Sync + 'static {}
29impl<T> HashBuilder for T where T: BuildHasher + Send + Sync + 'static {}
30
31pub type DefaultHasher = BuildHasherDefault<XxHash64>;
35
36#[derive(Debug, thiserror::Error)]
38pub enum CodeError {
39 #[error("exceed size limit")]
41 SizeLimit,
42 #[error("io error: {0}")]
44 Io(std::io::Error),
45 #[cfg(feature = "serde")]
46 #[error("bincode error: {0}")]
48 Bincode(bincode::Error),
49 #[error("unrecognized data: {0:?}")]
51 Unrecognized(Vec<u8>),
52 #[error("other error: {0}")]
54 Other(#[from] Box<dyn std::error::Error + Send + Sync>),
55}
56
57pub type CodeResult<T> = std::result::Result<T, CodeError>;
59
60impl From<std::io::Error> for CodeError {
61 fn from(err: std::io::Error) -> Self {
62 match err.kind() {
63 std::io::ErrorKind::WriteZero => Self::SizeLimit,
64 _ => Self::Io(err),
65 }
66 }
67}
68
69#[cfg(feature = "serde")]
70impl From<bincode::Error> for CodeError {
71 fn from(err: bincode::Error) -> Self {
72 match *err {
73 bincode::ErrorKind::SizeLimit => Self::SizeLimit,
74 bincode::ErrorKind::Io(e) => e.into(),
75 _ => Self::Bincode(err),
76 }
77 }
78}
79
80pub trait StorageKey: Key + Code {}
82impl<T> StorageKey for T where T: Key + Code {}
83
84pub trait StorageValue: Value + 'static + Code {}
86impl<T> StorageValue for T where T: Value + Code {}
87
88pub trait Code {
98 fn encode(&self, writer: &mut impl std::io::Write) -> std::result::Result<(), CodeError>;
100
101 fn decode(reader: &mut impl std::io::Read) -> std::result::Result<Self, CodeError>
103 where
104 Self: Sized;
105
106 fn estimated_size(&self) -> usize;
110}
111
112#[cfg(feature = "serde")]
113impl<T> Code for T
114where
115 T: serde::Serialize + serde::de::DeserializeOwned,
116{
117 fn encode(&self, writer: &mut impl std::io::Write) -> std::result::Result<(), CodeError> {
118 bincode::serialize_into(writer, self).map_err(CodeError::from)
119 }
120
121 fn decode(reader: &mut impl std::io::Read) -> std::result::Result<Self, CodeError> {
122 bincode::deserialize_from(reader).map_err(CodeError::from)
123 }
124
125 fn estimated_size(&self) -> usize {
126 bincode::serialized_size(self).unwrap() as usize
127 }
128}
129
130macro_rules! impl_serde_for_numeric_types {
131 ($($t:ty),*) => {
132 $(
133 #[cfg(not(feature = "serde"))]
134 impl Code for $t {
135 fn encode(&self, writer: &mut impl std::io::Write) -> std::result::Result<(), CodeError> {
136 writer.write_all(&self.to_le_bytes()).map_err(CodeError::from)
137 }
138
139 fn decode(reader: &mut impl std::io::Read) -> std::result::Result<Self, CodeError> {
140 let mut buf = [0u8; std::mem::size_of::<$t>()];
141 reader.read_exact(&mut buf).map_err(CodeError::from)?;
142 Ok(<$t>::from_le_bytes(buf))
143 }
144
145 fn estimated_size(&self) -> usize {
146 std::mem::size_of::<$t>()
147 }
148 }
149 )*
150 };
151}
152
153macro_rules! for_all_numeric_types {
154 ($macro:ident) => {
155 $macro! { u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize, f32, f64}
156 };
157}
158
159for_all_numeric_types! { impl_serde_for_numeric_types }
160
161#[cfg(not(feature = "serde"))]
162impl Code for bool {
163 fn encode(&self, writer: &mut impl std::io::Write) -> std::result::Result<(), CodeError> {
164 writer
165 .write_all(if *self { &[1u8] } else { &[0u8] })
166 .map_err(CodeError::from)
167 }
168
169 fn decode(reader: &mut impl std::io::Read) -> std::result::Result<Self, CodeError>
170 where
171 Self: Sized,
172 {
173 let mut buf = [0u8; 1];
174 reader.read_exact(&mut buf).map_err(CodeError::from)?;
175 match buf[0] {
176 0 => Ok(false),
177 1 => Ok(true),
178 _ => Err(CodeError::Unrecognized(buf.to_vec())),
179 }
180 }
181
182 fn estimated_size(&self) -> usize {
183 1
184 }
185}
186
187#[cfg(not(feature = "serde"))]
188impl Code for Vec<u8> {
189 fn encode(&self, writer: &mut impl std::io::Write) -> std::result::Result<(), CodeError> {
190 self.len().encode(writer)?;
191 writer.write_all(self).map_err(CodeError::from)
192 }
193
194 #[expect(clippy::uninit_vec)]
195 fn decode(reader: &mut impl std::io::Read) -> std::result::Result<Self, CodeError>
196 where
197 Self: Sized,
198 {
199 let len = usize::decode(reader)?;
200 let mut v = Vec::with_capacity(len);
201 unsafe {
202 v.set_len(len);
203 }
204 reader.read_exact(&mut v).map_err(CodeError::from)?;
205 Ok(v)
206 }
207
208 fn estimated_size(&self) -> usize {
209 std::mem::size_of::<usize>() + self.len()
210 }
211}
212
213#[cfg(not(feature = "serde"))]
214impl Code for String {
215 fn encode(&self, writer: &mut impl std::io::Write) -> std::result::Result<(), CodeError> {
216 self.len().encode(writer)?;
217 writer.write_all(self.as_bytes()).map_err(CodeError::from)
218 }
219
220 #[expect(clippy::uninit_vec)]
221 fn decode(reader: &mut impl std::io::Read) -> std::result::Result<Self, CodeError>
222 where
223 Self: Sized,
224 {
225 let len = usize::decode(reader)?;
226 let mut v = Vec::with_capacity(len);
227 unsafe {
228 v.set_len(len);
229 }
230 reader.read_exact(&mut v).map_err(CodeError::from)?;
231 String::from_utf8(v).map_err(|e| CodeError::Unrecognized(e.into_bytes()))
232 }
233
234 fn estimated_size(&self) -> usize {
235 std::mem::size_of::<usize>() + self.len()
236 }
237}
238
239#[cfg(test)]
240mod tests {
241 use super::*;
242
243 #[cfg(feature = "serde")]
244 mod serde {
245 use super::*;
246
247 #[test]
248 fn test_encode_overflow() {
249 let mut buf = [0u8; 4];
250 assert!(matches! {1u64.encode(&mut buf.as_mut()), Err(CodeError::SizeLimit)});
251 }
252 }
253
254 #[cfg(not(feature = "serde"))]
255 mod non_serde {
256 use super::*;
257
258 #[test]
259 fn test_encode_overflow() {
260 let mut buf = [0u8; 4];
261 assert!(matches! {1u64.encode(&mut buf.as_mut()), Err(CodeError::SizeLimit)});
262 }
263
264 macro_rules! impl_serde_test_for_numeric_types {
265 ($($t:ty),*) => {
266 paste::paste! {
267 $(
268 #[test]
269 fn [<test_ $t _serde>]() {
270 for a in [0 as $t, <$t>::MIN, <$t>::MAX] {
271 let mut buf = vec![0xffu8; a.estimated_size()];
272 a.encode(&mut buf.as_mut_slice()).unwrap();
273 let b = <$t>::decode(&mut buf.as_slice()).unwrap();
274 assert_eq!(a, b);
275 }
276 }
277 )*
278 }
279 };
280 }
281
282 for_all_numeric_types! { impl_serde_test_for_numeric_types }
283
284 #[test]
285 fn test_bool_serde() {
286 let a = true;
287 let mut buf = vec![0xffu8; a.estimated_size()];
288 a.encode(&mut buf.as_mut_slice()).unwrap();
289 let b = bool::decode(&mut buf.as_slice()).unwrap();
290 assert_eq!(a, b);
291 }
292
293 #[test]
294 fn test_vec_u8_serde() {
295 let mut a = vec![0u8; 42];
296 rand::fill(&mut a[..]);
297 let mut buf = vec![0xffu8; a.estimated_size()];
298 a.encode(&mut buf.as_mut_slice()).unwrap();
299 let b = Vec::<u8>::decode(&mut buf.as_slice()).unwrap();
300 assert_eq!(a, b);
301 }
302
303 #[test]
304 fn test_string_serde() {
305 let a = "hello world".to_string();
306 let mut buf = vec![0xffu8; a.estimated_size()];
307 a.encode(&mut buf.as_mut_slice()).unwrap();
308 let b = String::decode(&mut buf.as_slice()).unwrap();
309 assert_eq!(a, b);
310 }
311 }
312}