Skip to main content

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