midnight_serialize/
serializable.rs1use crate::tagged::Tagged;
15use std::{
16 borrow::{Borrow, Cow},
17 collections::{HashMap, HashSet},
18 io::Write,
19 marker::PhantomData,
20 sync::Arc,
21};
22
23pub const GLOBAL_TAG: &str = "midnight:";
24
25pub fn tagged_serialize<T: Serializable + Tagged>(
27 value: &T,
28 mut writer: impl Write,
29) -> std::io::Result<()> {
30 let tag = T::tag();
31 write!(&mut writer, "{GLOBAL_TAG}{tag}:")?;
32 value.serialize(&mut writer)
33}
34
35pub fn tagged_serialized_size<T: Serializable + Tagged>(value: &T) -> usize {
36 T::tag().len() + GLOBAL_TAG.len() + 1 + T::serialized_size(value)
37}
38
39pub trait Serializable {
43 fn serialize(&self, writer: &mut impl Write) -> std::io::Result<()>;
44 fn serialized_size(&self) -> usize;
45}
46
47impl<T: Serializable> Serializable for Vec<T> {
48 fn serialize(&self, writer: &mut impl Write) -> std::io::Result<()> {
49 (self.len() as u32).serialize(writer)?;
50 for elem in self {
51 elem.serialize(writer)?;
52 }
53 Ok(())
54 }
55 fn serialized_size(&self) -> usize {
56 self.iter()
57 .fold((self.len() as u64).serialized_size(), |acc, x| {
58 acc + x.serialized_size()
59 })
60 }
61}
62
63impl<K: Serializable + Ord, V: Serializable> Serializable for HashMap<K, V> {
64 fn serialize(&self, writer: &mut impl Write) -> std::io::Result<()> {
65 (self.len() as u32).serialize(writer)?;
66 let mut kvs = self.iter().collect::<Vec<_>>();
67 kvs.sort_by(|(k1, _), (k2, _)| k1.cmp(k2));
68 for (k, v) in kvs.into_iter() {
69 k.serialize(writer)?;
70 v.serialize(writer)?;
71 }
72 Ok(())
73 }
74
75 fn serialized_size(&self) -> usize {
76 self.iter().fold(4, |acc, (k, v)| {
77 acc + k.serialized_size() + v.serialized_size()
78 })
79 }
80}
81
82impl<T: Serializable + Ord> Serializable for HashSet<T> {
83 fn serialize(&self, writer: &mut impl Write) -> std::io::Result<()> {
84 (self.len() as u32).serialize(writer)?;
85 let mut elems = self.iter().collect::<Vec<_>>();
86 elems.sort();
87 for elem in elems.into_iter() {
88 elem.serialize(writer)?;
89 }
90
91 Ok(())
92 }
93
94 fn serialized_size(&self) -> usize {
95 self.iter()
96 .fold(4, |acc, elem| acc + elem.serialized_size())
97 }
98}
99
100impl<'a, T> Serializable for &'a T
101where
102 T: Serializable + 'a,
103 Self: Borrow<T>,
104{
105 fn serialize(&self, writer: &mut impl Write) -> std::io::Result<()> {
106 T::serialize(self, writer)
107 }
108
109 fn serialized_size(&self) -> usize {
110 T::serialized_size(self)
111 }
112}
113
114impl<T: Serializable> Serializable for Option<T> {
115 fn serialize(&self, writer: &mut impl Write) -> std::io::Result<()> {
116 match self {
117 Some(v) => {
118 1u8.serialize(writer)?;
119 v.serialize(writer)?;
120 Ok(())
121 }
122 None => {
123 0u8.serialize(writer)?;
124 Ok(())
125 }
126 }
127 }
128
129 fn serialized_size(&self) -> usize {
130 match self {
131 Some(v) => 1 + v.serialized_size(),
132 None => 1,
133 }
134 }
135}
136
137impl Serializable for str {
138 fn serialize(&self, writer: &mut impl Write) -> std::io::Result<()> {
139 (self.len() as u64).serialize(writer)?;
140 writer.write_all(self.as_bytes())
141 }
142
143 fn serialized_size(&self) -> usize {
144 let len = self.len();
145 (len as u64).serialized_size() + len
146 }
147}
148
149impl Serializable for String {
150 fn serialize(&self, writer: &mut impl Write) -> std::io::Result<()> {
151 str::serialize(self, writer)
152 }
153
154 fn serialized_size(&self) -> usize {
155 str::serialized_size(self)
156 }
157}
158
159impl Serializable for &str {
160 fn serialize(&self, writer: &mut impl Write) -> std::io::Result<()> {
161 str::serialize(self, writer)
162 }
163
164 fn serialized_size(&self) -> usize {
165 str::serialized_size(self)
166 }
167}
168
169impl<const N: usize> Serializable for [u8; N] {
170 fn serialize(&self, writer: &mut impl Write) -> std::io::Result<()> {
171 writer.write_all(&self[..])
172 }
173 fn serialized_size(&self) -> usize {
174 N
175 }
176}
177
178impl<T: ?Sized> Serializable for PhantomData<T> {
179 fn serialize(&self, _writer: &mut impl Write) -> std::io::Result<()> {
180 Ok(())
181 }
182 fn serialized_size(&self) -> usize {
183 0
184 }
185}
186
187impl<T: ?Sized> Tagged for PhantomData<T> {
188 fn tag() -> Cow<'static, str> {
189 Cow::Borrowed("()")
190 }
191 fn tag_unique_factor() -> String {
192 "()".into()
193 }
194}
195
196impl<T: Serializable> Serializable for Box<T> {
197 fn serialize(&self, writer: &mut impl Write) -> std::io::Result<()> {
198 T::serialize(self, writer)
199 }
200 fn serialized_size(&self) -> usize {
201 T::serialized_size(self)
202 }
203}
204
205impl<T: Serializable> Serializable for Arc<T> {
206 fn serialize(&self, writer: &mut impl Write) -> std::io::Result<()> {
207 T::serialize(self, writer)
208 }
209 fn serialized_size(&self) -> usize {
210 T::serialized_size(self)
211 }
212}
213
214impl<'a, T: ToOwned + ?Sized> Serializable for Cow<'a, T>
215where
216 T: Serializable,
217{
218 fn serialize(&self, writer: &mut impl Write) -> std::io::Result<()> {
219 T::serialize(self, writer)
220 }
221 fn serialized_size(&self) -> usize {
222 T::serialized_size(self)
223 }
224}
225
226impl<'a, T: ToOwned + ?Sized + Tagged> Tagged for Cow<'a, T> {
227 fn tag() -> Cow<'static, str> {
228 T::tag()
229 }
230 fn tag_unique_factor() -> String {
231 T::tag_unique_factor()
232 }
233}