1use alloc::collections::{BTreeMap, BTreeSet};
39use alloc::string::String;
40use alloc::vec::Vec;
41#[cfg(feature = "std")]
42use std::collections::{HashMap, HashSet};
43#[cfg(feature = "std")]
44use std::hash::{BuildHasher, Hash};
45
46use crate::codec::{Decode, Decoder};
47use crate::error::{Result, SerialError};
48use crate::traits::Deserialize;
49
50pub trait DeserializeView<'a>: Sized {
98 fn deserialize_view(decoder: &mut Decoder<'a>) -> Result<Self>;
105}
106
107#[inline]
127pub fn decode_view<'a, T: DeserializeView<'a>>(bytes: &'a [u8]) -> Result<T> {
128 let mut dec = Decoder::new(bytes);
129 let value = T::deserialize_view(&mut dec)?;
130 let remaining = dec.remaining();
131 if remaining != 0 {
132 return Err(SerialError::TrailingBytes { remaining });
133 }
134 Ok(value)
135}
136
137impl<'a> DeserializeView<'a> for &'a str {
142 #[inline]
143 fn deserialize_view(decoder: &mut Decoder<'a>) -> Result<Self> {
144 let bytes = decoder.read_length_prefixed_borrowed()?;
145 core::str::from_utf8(bytes).map_err(|_| SerialError::InvalidUtf8)
146 }
147}
148
149impl<'a> DeserializeView<'a> for &'a [u8] {
150 #[inline]
151 fn deserialize_view(decoder: &mut Decoder<'a>) -> Result<Self> {
152 decoder.read_length_prefixed_borrowed()
153 }
154}
155
156macro_rules! view_via_owned {
161 ($($t:ty),+ $(,)?) => {
162 $(
163 impl<'a> DeserializeView<'a> for $t {
164 #[inline]
165 fn deserialize_view(decoder: &mut Decoder<'a>) -> Result<Self> {
166 <$t as Deserialize>::deserialize(decoder)
167 }
168 }
169 )+
170 };
171}
172
173view_via_owned!(
174 u8,
175 u16,
176 u32,
177 u64,
178 u128,
179 usize,
180 i8,
181 i16,
182 i32,
183 i64,
184 i128,
185 isize,
186 bool,
187 f32,
188 f64,
189 (),
190 String,
191);
192
193impl<'a, T: DeserializeView<'a>> DeserializeView<'a> for Option<T> {
198 #[inline]
199 fn deserialize_view(decoder: &mut Decoder<'a>) -> Result<Self> {
200 match decoder.read_byte()? {
201 0x00 => Ok(None),
202 0x01 => Ok(Some(T::deserialize_view(decoder)?)),
203 tag => Err(SerialError::InvalidTag {
204 kind: "Option",
205 tag,
206 }),
207 }
208 }
209}
210
211impl<'a, T: DeserializeView<'a>, E: DeserializeView<'a>> DeserializeView<'a>
212 for core::result::Result<T, E>
213{
214 #[inline]
215 fn deserialize_view(decoder: &mut Decoder<'a>) -> Result<Self> {
216 match decoder.read_byte()? {
217 0x00 => Ok(Ok(T::deserialize_view(decoder)?)),
218 0x01 => Ok(Err(E::deserialize_view(decoder)?)),
219 tag => Err(SerialError::InvalidTag {
220 kind: "Result",
221 tag,
222 }),
223 }
224 }
225}
226
227impl<'a, T: DeserializeView<'a>, const N: usize> DeserializeView<'a> for [T; N] {
228 fn deserialize_view(decoder: &mut Decoder<'a>) -> Result<Self> {
229 let mut out: Vec<T> = Vec::with_capacity(N);
230 for _ in 0..N {
231 out.push(T::deserialize_view(decoder)?);
232 }
233 out.try_into().map_err(|_| SerialError::IntegerOutOfRange)
234 }
235}
236
237impl<'a, T: DeserializeView<'a>> DeserializeView<'a> for Vec<T> {
238 fn deserialize_view(decoder: &mut Decoder<'a>) -> Result<Self> {
239 let declared = <Decoder<'a> as crate::Decode>::read_varint_u64(decoder)?;
240 let max = <Decoder<'a> as crate::Decode>::max_alloc(decoder) as u64;
241 if declared > max {
242 return Err(SerialError::InvalidLength {
243 declared,
244 remaining: 0,
245 });
246 }
247 let len = usize::try_from(declared).map_err(|_| SerialError::IntegerOutOfRange)?;
248 let initial = len.min(4096);
249 let mut out = Vec::with_capacity(initial);
250 for _ in 0..len {
251 out.push(T::deserialize_view(decoder)?);
252 }
253 Ok(out)
254 }
255}
256
257macro_rules! view_tuple {
258 ($($name:ident),+) => {
259 impl<'a, $($name: DeserializeView<'a>),+> DeserializeView<'a> for ($($name,)+) {
260 #[inline]
261 fn deserialize_view(decoder: &mut Decoder<'a>) -> Result<Self> {
262 Ok(( $( $name::deserialize_view(decoder)?, )+ ))
263 }
264 }
265 };
266}
267
268view_tuple!(T0);
269view_tuple!(T0, T1);
270view_tuple!(T0, T1, T2);
271view_tuple!(T0, T1, T2, T3);
272view_tuple!(T0, T1, T2, T3, T4);
273view_tuple!(T0, T1, T2, T3, T4, T5);
274view_tuple!(T0, T1, T2, T3, T4, T5, T6);
275view_tuple!(T0, T1, T2, T3, T4, T5, T6, T7);
276view_tuple!(T0, T1, T2, T3, T4, T5, T6, T7, T8);
277view_tuple!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9);
278view_tuple!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10);
279view_tuple!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11);
280
281impl<'a, K, V> DeserializeView<'a> for BTreeMap<K, V>
286where
287 K: DeserializeView<'a> + Ord,
288 V: DeserializeView<'a>,
289{
290 fn deserialize_view(decoder: &mut Decoder<'a>) -> Result<Self> {
291 let declared = <Decoder<'a> as crate::Decode>::read_varint_u64(decoder)?;
292 let max = <Decoder<'a> as crate::Decode>::max_alloc(decoder) as u64;
293 if declared > max {
294 return Err(SerialError::InvalidLength {
295 declared,
296 remaining: 0,
297 });
298 }
299 let len = usize::try_from(declared).map_err(|_| SerialError::IntegerOutOfRange)?;
300 let mut out = BTreeMap::new();
301 for _ in 0..len {
302 let k = K::deserialize_view(decoder)?;
303 let v = V::deserialize_view(decoder)?;
304 let _ = out.insert(k, v);
305 }
306 Ok(out)
307 }
308}
309
310impl<'a, T> DeserializeView<'a> for BTreeSet<T>
311where
312 T: DeserializeView<'a> + Ord,
313{
314 fn deserialize_view(decoder: &mut Decoder<'a>) -> Result<Self> {
315 let declared = <Decoder<'a> as crate::Decode>::read_varint_u64(decoder)?;
316 let max = <Decoder<'a> as crate::Decode>::max_alloc(decoder) as u64;
317 if declared > max {
318 return Err(SerialError::InvalidLength {
319 declared,
320 remaining: 0,
321 });
322 }
323 let len = usize::try_from(declared).map_err(|_| SerialError::IntegerOutOfRange)?;
324 let mut out = BTreeSet::new();
325 for _ in 0..len {
326 let _ = out.insert(T::deserialize_view(decoder)?);
327 }
328 Ok(out)
329 }
330}
331
332#[cfg(feature = "std")]
333impl<'a, K, V, S> DeserializeView<'a> for HashMap<K, V, S>
334where
335 K: DeserializeView<'a> + Hash + Eq,
336 V: DeserializeView<'a>,
337 S: BuildHasher + Default,
338{
339 fn deserialize_view(decoder: &mut Decoder<'a>) -> Result<Self> {
340 let declared = <Decoder<'a> as crate::Decode>::read_varint_u64(decoder)?;
341 let max = <Decoder<'a> as crate::Decode>::max_alloc(decoder) as u64;
342 if declared > max {
343 return Err(SerialError::InvalidLength {
344 declared,
345 remaining: 0,
346 });
347 }
348 let len = usize::try_from(declared).map_err(|_| SerialError::IntegerOutOfRange)?;
349 let initial = len.min(4096);
350 let mut out = HashMap::with_capacity_and_hasher(initial, S::default());
351 for _ in 0..len {
352 let k = K::deserialize_view(decoder)?;
353 let v = V::deserialize_view(decoder)?;
354 let _ = out.insert(k, v);
355 }
356 Ok(out)
357 }
358}
359
360#[cfg(feature = "std")]
361impl<'a, T, S> DeserializeView<'a> for HashSet<T, S>
362where
363 T: DeserializeView<'a> + Hash + Eq,
364 S: BuildHasher + Default,
365{
366 fn deserialize_view(decoder: &mut Decoder<'a>) -> Result<Self> {
367 let declared = <Decoder<'a> as crate::Decode>::read_varint_u64(decoder)?;
368 let max = <Decoder<'a> as crate::Decode>::max_alloc(decoder) as u64;
369 if declared > max {
370 return Err(SerialError::InvalidLength {
371 declared,
372 remaining: 0,
373 });
374 }
375 let len = usize::try_from(declared).map_err(|_| SerialError::IntegerOutOfRange)?;
376 let initial = len.min(4096);
377 let mut out = HashSet::with_capacity_and_hasher(initial, S::default());
378 for _ in 0..len {
379 let _ = out.insert(T::deserialize_view(decoder)?);
380 }
381 Ok(out)
382 }
383}
384
385#[cfg(test)]
386mod tests {
387 use super::*;
388 use crate::encode;
389 use alloc::string::ToString;
390 use alloc::vec;
391
392 #[test]
393 fn borrowed_str_round_trips() {
394 let bytes = encode(&"hello").unwrap();
395 let view: &str = decode_view(&bytes).unwrap();
396 assert_eq!(view, "hello");
397 }
398
399 #[test]
400 fn borrowed_bytes_round_trip() {
401 let bytes = encode(&vec![1u8, 2, 3, 4, 5]).unwrap();
402 let view: &[u8] = decode_view(&bytes).unwrap();
403 assert_eq!(view, &[1, 2, 3, 4, 5]);
404 }
405
406 #[test]
407 fn primitive_view_decodes_like_owning() {
408 let bytes = encode(&42_u64).unwrap();
409 let n: u64 = decode_view(&bytes).unwrap();
410 assert_eq!(n, 42);
411 }
412
413 #[test]
414 fn option_borrowed_view_round_trips() {
415 let bytes = encode(&Some(String::from("hi"))).unwrap();
416 let v: Option<&str> = decode_view(&bytes).unwrap();
417 assert_eq!(v, Some("hi"));
418
419 let none_bytes = encode::<Option<String>>(&None).unwrap();
420 let v: Option<&str> = decode_view(&none_bytes).unwrap();
421 assert_eq!(v, None);
422 }
423
424 #[test]
425 fn tuple_with_borrowed_str_round_trips() {
426 let owned = (7_u64, String::from("hello"), true);
427 let bytes = encode(&owned).unwrap();
428 let view: (u64, &str, bool) = decode_view(&bytes).unwrap();
429 assert_eq!(view, (7, "hello", true));
430 }
431
432 #[test]
433 fn vec_of_borrowed_str_round_trips() {
434 let owned = vec![
435 String::from("alpha"),
436 String::from("beta"),
437 String::from("gamma"),
438 ];
439 let bytes = encode(&owned).unwrap();
440 let view: Vec<&str> = decode_view(&bytes).unwrap();
441 assert_eq!(view, vec!["alpha", "beta", "gamma"]);
442 }
443
444 #[test]
445 fn decode_view_rejects_trailing_bytes() {
446 let mut bytes = encode(&"hi").unwrap();
447 bytes.push(0xff);
448 let err = decode_view::<&str>(&bytes).expect_err("trailing bytes");
449 assert!(matches!(err, SerialError::TrailingBytes { remaining: 1 }));
450 }
451
452 #[test]
453 fn borrowed_str_with_invalid_utf8_is_rejected() {
454 let bytes = [0x02u8, 0xff, 0xff];
455 let err = decode_view::<&str>(&bytes).expect_err("invalid utf-8");
456 assert!(matches!(err, SerialError::InvalidUtf8));
457 }
458
459 #[test]
460 fn map_with_borrowed_keys_round_trips() {
461 let mut owned: BTreeMap<String, u32> = BTreeMap::new();
462 let _ = owned.insert("alpha".to_string(), 1);
463 let _ = owned.insert("beta".to_string(), 2);
464 let bytes = encode(&owned).unwrap();
465 let view: BTreeMap<&str, u32> = decode_view(&bytes).unwrap();
466 assert_eq!(view.get("alpha"), Some(&1));
467 assert_eq!(view.get("beta"), Some(&2));
468 }
469}