1use crate::any::ErasedValue;
2use crate::error::{self, Error};
3use crate::seed::ErasedDeserializeSeed;
4use alloc::boxed::Box;
5use serde::de::{Deserialize, DeserializeSeed, MapAccess};
6
7trait ErasedMapAccess<'de> {
8 fn erased_next_key_seed(
9 &mut self,
10 seed: &mut dyn ErasedDeserializeSeed<'de>,
11 ) -> Result<Option<ErasedValue>, Error>;
12
13 fn erased_next_value_seed(
14 &mut self,
15 seed: &mut dyn ErasedDeserializeSeed<'de>,
16 ) -> Result<ErasedValue, Error>;
17
18 fn erased_size_hint(&self) -> Option<usize>;
19}
20
21pub struct Map<'access, 'de> {
22 erased: Box<dyn ErasedMapAccess<'de> + 'access>,
23}
24
25impl<'access, 'de> Map<'access, 'de> {
26 pub(crate) fn new<A>(map: A) -> Self
27 where
28 A: MapAccess<'de> + 'access,
29 {
30 Map {
31 erased: Box::new(map),
32 }
33 }
34
35 pub fn deserialize<T>(self) -> Result<T, Error>
37 where
38 T: Deserialize<'de>,
39 {
40 T::deserialize(serde::de::value::MapAccessDeserializer::new(self))
41 }
42}
43
44impl<'access, 'de> MapAccess<'de> for Map<'access, 'de> {
45 type Error = Error;
46
47 fn next_key_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
48 where
49 T: DeserializeSeed<'de>,
50 {
51 self.erased
52 .erased_next_key_seed(&mut Some(seed))
53 .map(|erased_value| match erased_value {
54 Some(value) => Some(unsafe { ErasedValue::take::<T::Value>(value) }),
55 None => None,
56 })
57 }
58
59 fn next_value_seed<T>(&mut self, seed: T) -> Result<T::Value, Self::Error>
60 where
61 T: DeserializeSeed<'de>,
62 {
63 self.erased
64 .erased_next_value_seed(&mut Some(seed))
65 .map(|erased_value| unsafe { ErasedValue::take::<T::Value>(erased_value) })
66 }
67
68 fn size_hint(&self) -> Option<usize> {
69 self.erased.erased_size_hint()
70 }
71}
72
73impl<'de, Access> ErasedMapAccess<'de> for Access
74where
75 Access: MapAccess<'de>,
76{
77 fn erased_next_key_seed(
78 &mut self,
79 seed: &mut dyn ErasedDeserializeSeed<'de>,
80 ) -> Result<Option<ErasedValue>, Error> {
81 self.next_key_seed(seed).map_err(error::erase)
82 }
83
84 fn erased_next_value_seed(
85 &mut self,
86 seed: &mut dyn ErasedDeserializeSeed<'de>,
87 ) -> Result<ErasedValue, Error> {
88 self.next_value_seed(seed).map_err(error::erase)
89 }
90
91 fn erased_size_hint(&self) -> Option<usize> {
92 self.size_hint()
93 }
94}