zvariant/
de.rs

1use serde::de::{self, DeserializeSeed, VariantAccess, Visitor};
2
3use std::{marker::PhantomData, str};
4
5#[cfg(unix)]
6use std::os::fd::{AsFd, AsRawFd};
7
8#[cfg(feature = "gvariant")]
9use crate::gvariant::Deserializer as GVDeserializer;
10use crate::{
11    container_depths::ContainerDepths, dbus::Deserializer as DBusDeserializer, serialized::Context,
12    utils::*, Basic, Error, Result, Signature,
13};
14
15/// Our deserialization implementation.
16#[derive(Debug)]
17pub(crate) struct DeserializerCommon<'de, 'sig, 'f, F> {
18    pub(crate) ctxt: Context,
19    pub(crate) bytes: &'de [u8],
20
21    #[cfg(unix)]
22    pub(crate) fds: Option<&'f [F]>,
23    #[cfg(not(unix))]
24    pub(crate) fds: PhantomData<&'f F>,
25
26    pub(crate) pos: usize,
27
28    pub(crate) signature: &'sig Signature,
29
30    pub(crate) container_depths: ContainerDepths,
31}
32
33/// Our deserialization implementation.
34///
35/// Using this deserializer involves an redirection to the actual deserializer. It's best
36/// to use the serialization functions, e.g [`crate::to_bytes`] or specific serializers,
37/// [`crate::dbus::Deserializer`] or [`crate::zvariant::Deserializer`].
38pub(crate) enum Deserializer<'ser, 'sig, 'f, F> {
39    DBus(DBusDeserializer<'ser, 'sig, 'f, F>),
40    #[cfg(feature = "gvariant")]
41    GVariant(GVDeserializer<'ser, 'sig, 'f, F>),
42}
43
44#[cfg(unix)]
45impl<F> DeserializerCommon<'_, '_, '_, F>
46where
47    F: AsFd,
48{
49    pub fn get_fd(&self, idx: u32) -> Result<i32> {
50        self.fds
51            .and_then(|fds| fds.get(idx as usize).map(|fd| fd.as_fd().as_raw_fd()))
52            .ok_or(Error::UnknownFd)
53    }
54}
55
56impl<'de, F> DeserializerCommon<'de, '_, '_, F> {
57    pub fn parse_padding(&mut self, alignment: usize) -> Result<usize> {
58        let padding = padding_for_n_bytes(self.abs_pos(), alignment);
59        if padding > 0 {
60            if self.pos + padding > self.bytes.len() {
61                return Err(serde::de::Error::invalid_length(
62                    self.bytes.len(),
63                    &format!(">= {}", self.pos + padding).as_str(),
64                ));
65            }
66
67            for i in 0..padding {
68                let byte = self.bytes[self.pos + i];
69                if byte != 0 {
70                    return Err(Error::PaddingNot0(byte));
71                }
72            }
73            self.pos += padding;
74        }
75
76        Ok(padding)
77    }
78
79    pub fn prep_deserialize_basic<T>(&mut self) -> Result<()>
80    where
81        T: Basic,
82    {
83        self.parse_padding(T::alignment(self.ctxt.format()))?;
84
85        Ok(())
86    }
87
88    pub fn next_slice(&mut self, len: usize) -> Result<&'de [u8]> {
89        if self.pos + len > self.bytes.len() {
90            return Err(serde::de::Error::invalid_length(
91                self.bytes.len(),
92                &format!(">= {}", self.pos + len).as_str(),
93            ));
94        }
95
96        let slice = &self.bytes[self.pos..self.pos + len];
97        self.pos += len;
98
99        Ok(slice)
100    }
101
102    pub fn next_const_size_slice<T>(&mut self) -> Result<&[u8]>
103    where
104        T: Basic,
105    {
106        self.prep_deserialize_basic::<T>()?;
107
108        self.next_slice(T::alignment(self.ctxt.format()))
109    }
110
111    pub fn abs_pos(&self) -> usize {
112        self.ctxt.position() + self.pos
113    }
114}
115
116macro_rules! deserialize_method {
117    ($method:ident($($arg:ident: $type:ty),*)) => {
118        #[inline]
119        fn $method<V>(self, $($arg: $type,)* visitor: V) -> Result<V::Value>
120        where
121            V: Visitor<'de>,
122        {
123            match self {
124                #[cfg(feature = "gvariant")]
125                Deserializer::GVariant(de) => {
126                    de.$method($($arg,)* visitor)
127                }
128                Deserializer::DBus(de) => {
129                    de.$method($($arg,)* visitor)
130                }
131            }
132        }
133    }
134}
135
136impl<'de, #[cfg(unix)] F: AsFd, #[cfg(not(unix))] F> de::Deserializer<'de>
137    for &mut Deserializer<'de, '_, '_, F>
138{
139    type Error = Error;
140
141    deserialize_method!(deserialize_any());
142    deserialize_method!(deserialize_bool());
143    deserialize_method!(deserialize_i8());
144    deserialize_method!(deserialize_i16());
145    deserialize_method!(deserialize_i32());
146    deserialize_method!(deserialize_i64());
147    deserialize_method!(deserialize_u8());
148    deserialize_method!(deserialize_u16());
149    deserialize_method!(deserialize_u32());
150    deserialize_method!(deserialize_u64());
151    deserialize_method!(deserialize_f32());
152    deserialize_method!(deserialize_f64());
153    deserialize_method!(deserialize_char());
154    deserialize_method!(deserialize_str());
155    deserialize_method!(deserialize_string());
156    deserialize_method!(deserialize_bytes());
157    deserialize_method!(deserialize_byte_buf());
158    deserialize_method!(deserialize_option());
159    deserialize_method!(deserialize_unit());
160    deserialize_method!(deserialize_unit_struct(n: &'static str));
161    deserialize_method!(deserialize_newtype_struct(n: &'static str));
162    deserialize_method!(deserialize_seq());
163    deserialize_method!(deserialize_map());
164    deserialize_method!(deserialize_tuple(n: usize));
165    deserialize_method!(deserialize_tuple_struct(n: &'static str, l: usize));
166    deserialize_method!(deserialize_struct(
167        n: &'static str,
168        f: &'static [&'static str]
169    ));
170    deserialize_method!(deserialize_enum(
171        n: &'static str,
172        f: &'static [&'static str]
173    ));
174    deserialize_method!(deserialize_identifier());
175    deserialize_method!(deserialize_ignored_any());
176
177    fn is_human_readable(&self) -> bool {
178        false
179    }
180}
181
182#[derive(Debug)]
183pub(crate) enum ValueParseStage {
184    Signature,
185    Value,
186    Done,
187}
188
189pub(crate) fn deserialize_any<'de, 'f, D, V>(
190    de: D,
191    signature: &Signature,
192    visitor: V,
193) -> Result<V::Value>
194where
195    D: de::Deserializer<'de, Error = Error>,
196    V: Visitor<'de>,
197{
198    match signature {
199        Signature::Unit => de.deserialize_unit(visitor),
200        Signature::U8 => de.deserialize_u8(visitor),
201        Signature::Bool => de.deserialize_bool(visitor),
202        Signature::I16 => de.deserialize_i16(visitor),
203        Signature::U16 => de.deserialize_u16(visitor),
204        Signature::I32 => de.deserialize_i32(visitor),
205        #[cfg(unix)]
206        Signature::Fd => de.deserialize_i32(visitor),
207        Signature::U32 => de.deserialize_u32(visitor),
208        Signature::I64 => de.deserialize_i64(visitor),
209        Signature::U64 => de.deserialize_u64(visitor),
210        Signature::F64 => de.deserialize_f64(visitor),
211        Signature::Str | Signature::ObjectPath | Signature::Signature => {
212            de.deserialize_str(visitor)
213        }
214        Signature::Variant => de.deserialize_seq(visitor),
215        Signature::Array(_) => de.deserialize_seq(visitor),
216        Signature::Dict { .. } => de.deserialize_map(visitor),
217        Signature::Structure { .. } => de.deserialize_seq(visitor),
218        #[cfg(feature = "gvariant")]
219        Signature::Maybe(_) => de.deserialize_option(visitor),
220    }
221}
222
223// Enum handling is very generic so it can be here and specific deserializers can use this.
224pub(crate) struct Enum<D, F> {
225    pub(crate) de: D,
226    pub(crate) name: &'static str,
227    pub(crate) _phantom: PhantomData<F>,
228}
229
230impl<'de, D, F> VariantAccess<'de> for Enum<D, F>
231where
232    D: de::Deserializer<'de, Error = Error>,
233{
234    type Error = Error;
235
236    fn unit_variant(self) -> std::result::Result<(), Self::Error> {
237        Ok(())
238    }
239
240    fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value>
241    where
242        T: DeserializeSeed<'de>,
243    {
244        seed.deserialize(self.de)
245    }
246
247    fn tuple_variant<V>(self, _len: usize, visitor: V) -> Result<V::Value>
248    where
249        V: Visitor<'de>,
250    {
251        de::Deserializer::deserialize_struct(self.de, self.name, &[], visitor)
252    }
253
254    fn struct_variant<V>(self, fields: &'static [&'static str], visitor: V) -> Result<V::Value>
255    where
256        V: Visitor<'de>,
257    {
258        de::Deserializer::deserialize_struct(self.de, self.name, fields, visitor)
259    }
260}