1use std::fmt::Debug;
2use std::io::Cursor;
3use std::sync::Arc;
4use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
5
6pub trait Cacheable: Debug {
8 fn to_bytes(&self) -> Vec<u8>;
10
11 fn from_bytes(bytes: &[u8]) -> anyhow::Result<Self>
13 where
14 Self: Sized;
15
16 fn to_hex(&self) -> String {
17 hex::encode(self.to_bytes())
18 }
19
20 fn from_hex(hex: &str) -> anyhow::Result<Self>
21 where
22 Self: Sized,
23 {
24 let bytes = hex::decode(hex)?;
25 Self::from_bytes(&bytes)
26 }
27}
28
29impl Cacheable for () {
30 fn to_bytes(&self) -> Vec<u8> {
31 vec![]
32 }
33
34 fn from_bytes(_bytes: &[u8]) -> anyhow::Result<Self> {
35 Ok(())
36 }
37}
38
39impl<T: Cacheable> Cacheable for Arc<T> {
40 fn to_bytes(&self) -> Vec<u8> {
41 self.as_ref().to_bytes()
42 }
43
44 fn from_bytes(bytes: &[u8]) -> anyhow::Result<Self>
45 where
46 Self: Sized,
47 {
48 Ok(Arc::new(T::from_bytes(bytes)?))
49 }
50}
51
52impl Cacheable for Vec<u8> {
53 fn to_bytes(&self) -> Vec<u8> {
54 self.clone()
55 }
56
57 fn from_bytes(bytes: &[u8]) -> anyhow::Result<Self>
58 where
59 Self: Sized,
60 {
61 Ok(bytes.to_vec())
62 }
63}
64
65impl Cacheable for String {
66 fn to_bytes(&self) -> Vec<u8> {
67 self.as_bytes().to_vec()
68 }
69
70 fn from_bytes(bytes: &[u8]) -> anyhow::Result<Self>
71 where
72 Self: Sized,
73 {
74 Ok(Self::from_utf8(bytes.to_vec())?)
75 }
76}
77
78macro_rules! impl_numeric {
79 ($ty: ty) => {
80 impl Cacheable for $ty {
81 fn to_bytes(&self) -> Vec<u8> {
82 let num = *self as u128;
83 let mut wtr = Vec::with_capacity(16);
84 wtr.write_u128::<BigEndian>(num).unwrap();
85
86 wtr
87 }
88
89 fn from_bytes(bytes: &[u8]) -> anyhow::Result<Self>
90 where
91 Self: Sized
92 {
93 let mut rdr = Cursor::new(bytes);
94 let num = rdr.read_u128::<BigEndian>().unwrap();
95
96 Ok(num as $ty)
97 }
98 }
99 };
100 ($($ty: ty),+ $(,)?) => {
101 $(
102 impl_numeric!($ty);
103 )*
104 };
105}
106
107impl_numeric!(
108 u128, i128,
109 u64, i64,
110 u32, i32,
111 u16, i16,
112 u8, i8,
113 usize, isize,
114);
115
116impl Cacheable for bool {
117 fn to_bytes(&self) -> Vec<u8> {
118 if *self {
119 Cacheable::to_bytes(&1)
120 } else {
121 Cacheable::to_bytes(&0)
122 }
123 }
124
125 fn from_bytes(bytes: &[u8]) -> anyhow::Result<Self>
126 where
127 Self: Sized,
128 {
129 Ok(!bytes.iter().all(|byte| *byte == 0))
130 }
131}
132
133#[cfg(test)]
134mod tests {
135 use super::*;
136 use rand::{random, Rng, thread_rng};
137 use rand::distributions::Alphanumeric;
138
139 #[tokio::test]
140 async fn it_works() -> anyhow::Result<()> { Ok(()) }
141
142 #[test]
143 fn test_string() -> anyhow::Result<()> {
144 for _ in 0..1024 {
145 let t: String = (0..32)
146 .map(|_| thread_rng().sample(Alphanumeric) as char)
147 .collect();
148
149 let v = Cacheable::to_bytes(&t);
150 let d: String = Cacheable::from_bytes(&v).unwrap();
151
152 assert_eq!(t, d);
153 }
154
155 Ok(())
156 }
157
158 #[test]
159 fn test_numeric() -> anyhow::Result<()> {
160 macro_rules! test {
161 ($ty: ty) => {
162 for _ in 0..1024 {
163 let num: $ty = random();
164 let v = Cacheable::to_bytes(&num);
165 let d: $ty = Cacheable::from_bytes(&v).unwrap();
166 assert_eq!(num, d);
167 }
168 };
169 ($($ty: ty),+ $(,)?) => {
170 $(test!($ty);)+
171 };
172 }
173
174 test!(
175 u128, i128,
176 u64, i64,
177 u32, i32,
178 u16, i16,
179 u8, i8,
180 usize, isize,
181 );
182
183 macro_rules! test_arc {
184 ($ty: ty) => {
185 for _ in 0..1024 {
186 let num: $ty = rand::thread_rng().gen();
187 let num = Arc::new(num);
188 let v = Cacheable::to_bytes(&num);
189 let arc_d: Arc<$ty> = Cacheable::from_bytes(&v).unwrap();
190 let d: $ty = Cacheable::from_bytes(&v).unwrap();
191 assert_eq!(num, arc_d);
192 assert_eq!(d, *arc_d);
193 }
194 };
195 ($($ty: ty),+ $(,)?) => {
196 $(test_arc!($ty);)+
197 };
198 }
199
200 test_arc!(
201 u128, i128,
202 u64, i64,
203 u32, i32,
204 u16, i16,
205 u8, i8,
206 usize, isize,
207 );
208
209 Ok(())
210 }
211
212 #[test]
213 fn test_boolean() -> anyhow::Result<()> {
214 for _ in 0..1024 {
215 let b: bool = random();
216 let v = b.to_bytes();
217 let d: bool = Cacheable::from_bytes(&v).unwrap();
218
219 assert_eq!(b, d);
220 }
221
222 Ok(())
223 }
224}