midnight_serialize/
deserializable.rs1use crate::VecExt;
15use crate::serializable::GLOBAL_TAG;
16use crate::tagged::Tagged;
17use std::borrow::Cow;
18use std::io::{BufRead, Read};
19use std::marker::PhantomData;
20use std::sync::Arc;
21use std::{collections::HashMap, collections::HashSet, hash::Hash};
22
23#[cfg(debug_assertions)]
24pub const RECURSION_LIMIT: u32 = 50;
25#[cfg(not(debug_assertions))]
26pub const RECURSION_LIMIT: u32 = 250;
27
28pub fn tagged_deserialize<T: Deserializable + Tagged>(reader: impl Read) -> std::io::Result<T> {
30 tagged_deserialize_inner(reader, true)
31}
32
33pub fn tagged_deserialize_sequence<T: Deserializable + Tagged>(
34 mut reader: impl BufRead,
35) -> std::io::Result<Vec<T>> {
36 let mut res = vec![];
37 while !reader.fill_buf()?.is_empty() {
38 res.push(tagged_deserialize_inner(&mut reader, false)?);
39 }
40 Ok(res)
41}
42
43fn tagged_deserialize_inner<T: Deserializable + Tagged>(
44 mut reader: impl Read,
45 ensure_consumed: bool,
46) -> std::io::Result<T> {
47 let tag_expected = format!("{GLOBAL_TAG}{}:", T::tag());
48 let mut read_tag = vec![0u8; tag_expected.len()];
49 let mut remaining_tag_buf = &mut read_tag[..];
50 while !remaining_tag_buf.is_empty() {
51 let read = reader.read(remaining_tag_buf)?;
52 if read == 0 {
53 let rem = remaining_tag_buf.len();
54 let len = read_tag.len() - rem;
55 read_tag.truncate(len);
56 break;
57 }
58 remaining_tag_buf = &mut remaining_tag_buf[read..];
59 }
60 if read_tag != tag_expected.as_bytes() {
61 let sanitised = String::from_utf8_lossy(&read_tag).replace(
62 |c: char| -> bool { !c.is_ascii_alphanumeric() && !":_-()[],".contains(c) },
63 "�",
64 );
65 return Err(std::io::Error::new(
66 std::io::ErrorKind::InvalidData,
67 format!("expected header tag '{tag_expected}', got '{sanitised}'"),
68 ));
69 }
70 let value = <T as Deserializable>::deserialize(&mut reader, 0)?;
71
72 if !ensure_consumed {
73 return Ok(value);
74 }
75
76 #[allow(clippy::unbuffered_bytes)] let count = reader.bytes().count(); if count == 0 {
80 return Ok(value);
81 }
82
83 Err(std::io::Error::new(
84 std::io::ErrorKind::InvalidData,
85 format!(
86 "Not all bytes read deserializing '{}'; {} bytes remaining",
87 tag_expected, count
88 ),
89 ))
90}
91
92pub trait Deserializable
93where
94 Self: Sized,
95{
96 const LIMIT_RECURSION: bool = true;
97
98 fn deserialize(reader: &mut impl Read, recursion_depth: u32) -> std::io::Result<Self>;
99
100 fn check_rec(depth: &mut u32) -> std::io::Result<()> {
101 if Self::LIMIT_RECURSION {
102 *depth += 1;
103 if *depth > RECURSION_LIMIT {
104 return Err(std::io::Error::new(
105 std::io::ErrorKind::InvalidData,
106 "exceeded recursion depth deserializing",
107 ));
108 }
109 }
110 Ok(())
111 }
112}
113
114impl<T: Deserializable> Deserializable for Vec<T> {
115 fn deserialize(reader: &mut impl Read, mut recursion_depth: u32) -> std::io::Result<Self> {
116 Self::check_rec(&mut recursion_depth)?;
117 let len = <u32 as Deserializable>::deserialize(reader, recursion_depth)?;
118 let mut result = Vec::with_bounded_capacity(len as usize);
119 for _ in 0..len {
120 result.push(<T as Deserializable>::deserialize(reader, recursion_depth)?);
121 }
122 Ok(result)
123 }
124}
125
126impl<K: Deserializable + PartialOrd + Hash + Eq, V: Deserializable> Deserializable
127 for HashMap<K, V>
128{
129 fn deserialize(reader: &mut impl Read, mut recursion_depth: u32) -> std::io::Result<Self> {
130 Self::check_rec(&mut recursion_depth)?;
131 let len = <u32 as Deserializable>::deserialize(reader, recursion_depth)?;
132 let mut result = HashMap::new();
133 for _ in 0..len {
134 let k = <K as Deserializable>::deserialize(reader, recursion_depth)?;
135 let v = <V as Deserializable>::deserialize(reader, recursion_depth)?;
136 result.insert(k, v);
137 }
138 Ok(result)
139 }
140}
141
142impl<T: Deserializable + Hash + Eq> Deserializable for HashSet<T> {
143 fn deserialize(reader: &mut impl Read, mut recursion_depth: u32) -> std::io::Result<Self> {
144 Self::check_rec(&mut recursion_depth)?;
145 let len = <u32 as Deserializable>::deserialize(reader, recursion_depth)?;
146 let mut result = HashSet::new();
147 for _ in 0..len {
148 result.insert(<T as Deserializable>::deserialize(reader, recursion_depth)?);
149 }
150 Ok(result)
151 }
152}
153
154impl<T: Deserializable> Deserializable for Option<T> {
155 fn deserialize(reader: &mut impl Read, mut recursion_depth: u32) -> std::io::Result<Self> {
156 Self::check_rec(&mut recursion_depth)?;
157 let some = <u8 as Deserializable>::deserialize(reader, recursion_depth)?;
158 match some {
159 0 => Ok(None),
160 1 => Ok(Some(<T as Deserializable>::deserialize(
161 reader,
162 recursion_depth,
163 )?)),
164 _ => Err(std::io::Error::new(
165 std::io::ErrorKind::InvalidData,
166 format!("Invalid discriminant: {}.", some),
167 )),
168 }
169 }
170}
171
172impl<T: Deserializable> Deserializable for Arc<T> {
173 fn deserialize(
174 reader: &mut impl Read,
175 mut recursion_depth: u32,
176 ) -> Result<Self, std::io::Error> {
177 Self::check_rec(&mut recursion_depth)?;
178 Ok(Arc::new(T::deserialize(reader, recursion_depth)?))
179 }
180}
181
182impl<const N: usize> Deserializable for [u8; N] {
183 fn deserialize(reader: &mut impl Read, _recursion_depth: u32) -> std::io::Result<Self> {
184 let mut res = [0u8; N];
185 reader.read_exact(&mut res[..])?;
186 Ok(res)
187 }
188}
189
190impl<T: ?Sized> Deserializable for PhantomData<T> {
191 fn deserialize(_reader: &mut impl Read, _recursion_depth: u32) -> std::io::Result<Self> {
192 Ok(PhantomData)
193 }
194}
195
196impl<T: Deserializable> Deserializable for Box<T> {
197 fn deserialize(reader: &mut impl Read, recursion_depth: u32) -> std::io::Result<Self> {
198 T::deserialize(reader, recursion_depth).map(Box::new)
199 }
200}
201
202impl<'a, T: ToOwned + ?Sized> Deserializable for Cow<'a, T>
203where
204 T::Owned: Deserializable,
205{
206 fn deserialize(reader: &mut impl Read, recursion_depth: u32) -> std::io::Result<Self> {
207 <T::Owned>::deserialize(reader, recursion_depth).map(Cow::Owned)
208 }
209}