zvariant/
signature_parser.rs

1use std::ops::{Bound, RangeBounds};
2
3use crate::{subslice, Basic, ObjectPath, Result, Signature, STRUCT_SIG_END_CHAR};
4
5#[cfg(unix)]
6use crate::Fd;
7
8#[cfg(feature = "gvariant")]
9use crate::utils::MAYBE_SIGNATURE_CHAR;
10use crate::utils::{
11    ARRAY_SIGNATURE_CHAR, DICT_ENTRY_SIG_END_CHAR, DICT_ENTRY_SIG_START_CHAR,
12    STRUCT_SIG_START_CHAR, VARIANT_SIGNATURE_CHAR,
13};
14
15#[derive(Debug, Clone)]
16pub(crate) struct SignatureParser<'s> {
17    signature: Signature<'s>,
18    pos: usize,
19    end: usize,
20}
21
22impl<'s> SignatureParser<'s> {
23    pub fn new(signature: Signature<'s>) -> Self {
24        let end = signature.len();
25
26        Self {
27            signature,
28            pos: 0,
29            end,
30        }
31    }
32
33    pub(crate) unsafe fn from_bytes_unchecked(signature: &'s [u8]) -> Result<Self> {
34        if signature.len() > 255 {
35            return Err(serde::de::Error::invalid_length(
36                signature.len(),
37                &"<= 255 characters",
38            ));
39        }
40
41        let signature = Signature::from_bytes_unchecked(signature);
42        Ok(Self::new(signature))
43    }
44
45    pub fn validate(signature: &'s [u8]) -> Result<()> {
46        // SAFETY: the parser is only used to validate the signature
47        for s in unsafe { Self::from_bytes_unchecked(signature)? } {
48            s?;
49        }
50        Ok(())
51    }
52
53    pub fn signature(&self) -> Signature<'_> {
54        self.signature.slice(self.pos..self.end)
55    }
56
57    pub fn next_char(&self) -> Result<char> {
58        subslice(self.signature.as_bytes(), self.pos).map(|b| *b as char)
59    }
60
61    #[inline]
62    pub fn skip_char(&mut self) -> Result<()> {
63        self.skip_chars(1)
64    }
65
66    pub fn skip_chars(&mut self, num_chars: usize) -> Result<()> {
67        self.pos += num_chars;
68
69        // We'll be going one char beyond at the end of parsing but not beyond that.
70        if self.pos > self.end {
71            return Err(serde::de::Error::invalid_length(
72                self.signature.len(),
73                &format!(">= {} characters", self.pos).as_str(),
74            ));
75        }
76
77        Ok(())
78    }
79
80    #[inline]
81    pub fn len(&self) -> usize {
82        self.end - self.pos
83    }
84
85    #[inline]
86    pub fn done(&self) -> bool {
87        self.pos == self.end
88    }
89
90    /// Returns a slice of `self` for the provided range.
91    ///
92    /// # Panics
93    ///
94    /// Requires that begin <= end and end <= self.len(), otherwise slicing will panic.
95    pub fn slice(&self, range: impl RangeBounds<usize>) -> Self {
96        let len = self.len();
97
98        let pos = match range.start_bound() {
99            Bound::Included(&n) => n,
100            Bound::Excluded(&n) => n + 1,
101            Bound::Unbounded => 0,
102        };
103
104        let end = match range.end_bound() {
105            Bound::Included(&n) => n + 1,
106            Bound::Excluded(&n) => n,
107            Bound::Unbounded => len,
108        };
109
110        assert!(
111            pos <= end,
112            "range start must not be greater than end: {:?} > {:?}",
113            pos,
114            end,
115        );
116        assert!(end <= len, "range end out of bounds: {:?} > {:?}", end, len,);
117
118        let mut clone = self.clone();
119        clone.pos += pos;
120        clone.end = self.pos + end;
121
122        clone
123    }
124
125    /// Get the next signature and increment the position.
126    pub fn parse_next_signature(&mut self) -> Result<Signature<'s>> {
127        let len = &self.next_signature()?.len();
128        let pos = self.pos;
129        self.pos += len;
130
131        // We'll be going one char beyond at the end of parsing but not beyond that.
132        if self.pos > self.end {
133            return Err(serde::de::Error::invalid_length(
134                self.signature.len(),
135                &format!(">= {} characters", self.pos).as_str(),
136            ));
137        }
138
139        Ok(self.signature.slice(pos..self.pos))
140    }
141
142    /// Get the next signature but don't increment the position.
143    pub fn next_signature(&self) -> Result<Signature<'_>> {
144        match self
145            .signature()
146            .as_bytes()
147            .first()
148            .map(|b| *b as char)
149            .ok_or_else(|| -> crate::Error {
150                serde::de::Error::invalid_length(0, &">= 1 character")
151            })? {
152            u8::SIGNATURE_CHAR
153            | bool::SIGNATURE_CHAR
154            | i16::SIGNATURE_CHAR
155            | u16::SIGNATURE_CHAR
156            | i32::SIGNATURE_CHAR
157            | u32::SIGNATURE_CHAR
158            | i64::SIGNATURE_CHAR
159            | u64::SIGNATURE_CHAR
160            | f64::SIGNATURE_CHAR
161            | <&str>::SIGNATURE_CHAR
162            | ObjectPath::SIGNATURE_CHAR
163            | Signature::SIGNATURE_CHAR
164            | VARIANT_SIGNATURE_CHAR => Ok(self.signature_slice(0, 1)),
165            #[cfg(unix)]
166            Fd::SIGNATURE_CHAR => Ok(self.signature_slice(0, 1)),
167            ARRAY_SIGNATURE_CHAR => self.next_array_signature(),
168            STRUCT_SIG_START_CHAR => self.next_structure_signature(),
169            DICT_ENTRY_SIG_START_CHAR => self.next_dict_entry_signature(),
170            #[cfg(feature = "gvariant")]
171            MAYBE_SIGNATURE_CHAR => self.next_maybe_signature(),
172            c => Err(serde::de::Error::invalid_value(
173                serde::de::Unexpected::Char(c),
174                &"a valid signature character",
175            )),
176        }
177    }
178
179    fn next_single_child_type_container_signature(
180        &self,
181        expected_sig_prefix: char,
182    ) -> Result<Signature<'_>> {
183        let signature = self.signature();
184
185        if signature.len() < 2 {
186            return Err(serde::de::Error::invalid_length(
187                signature.len(),
188                &">= 2 characters",
189            ));
190        }
191
192        // We can't get None here cause we already established there is are least 2 chars above
193        let c = signature
194            .as_bytes()
195            .first()
196            .map(|b| *b as char)
197            .expect("empty signature");
198        if c != expected_sig_prefix {
199            return Err(serde::de::Error::invalid_value(
200                serde::de::Unexpected::Char(c),
201                &expected_sig_prefix.to_string().as_str(),
202            ));
203        }
204
205        // There should be a valid complete signature after 'a' but not more than 1
206        let child_parser = self.slice(1..);
207        let child_len = child_parser.next_signature()?.len();
208
209        Ok(self.signature_slice(0, child_len + 1))
210    }
211
212    fn next_array_signature(&self) -> Result<Signature<'_>> {
213        self.next_single_child_type_container_signature(ARRAY_SIGNATURE_CHAR)
214    }
215
216    #[cfg(feature = "gvariant")]
217    fn next_maybe_signature(&self) -> Result<Signature<'_>> {
218        self.next_single_child_type_container_signature(MAYBE_SIGNATURE_CHAR)
219    }
220
221    fn next_structure_signature(&self) -> Result<Signature<'_>> {
222        let signature = self.signature();
223
224        if signature.len() < 3 {
225            return Err(serde::de::Error::invalid_length(
226                signature.len(),
227                &">= 2 characters",
228            ));
229        }
230
231        let mut bytes = signature.as_bytes().iter();
232        // We can't get None here cause we already established there are at least 2 chars above
233        let c = bytes.next().map(|b| *b as char).expect("empty signature");
234        if c != STRUCT_SIG_START_CHAR {
235            return Err(serde::de::Error::invalid_value(
236                serde::de::Unexpected::Char(c),
237                &crate::STRUCT_SIG_START_STR,
238            ));
239        }
240        if bytes.next().map(|b| *b as char).expect("empty signature") == STRUCT_SIG_END_CHAR {
241            return Err(serde::de::Error::invalid_value(
242                serde::de::Unexpected::Str("()"),
243                &"at least one field signature between `(` and `)`",
244            ));
245        }
246
247        let mut fields_sig_len = 0;
248        let mut fields_parser = self.slice(1..);
249        while !fields_parser.done() && fields_parser.next_char()? != STRUCT_SIG_END_CHAR {
250            fields_sig_len += fields_parser.parse_next_signature()?.len();
251        }
252        let c = fields_parser.next_char()?;
253        if c != STRUCT_SIG_END_CHAR {
254            return Err(serde::de::Error::invalid_value(
255                serde::de::Unexpected::Char(c),
256                &crate::STRUCT_SIG_END_STR,
257            ));
258        }
259
260        // The `(`, fields signatures and `)`.
261        Ok(self.signature_slice(0, fields_sig_len + 2))
262    }
263
264    fn next_dict_entry_signature(&self) -> Result<Signature<'_>> {
265        let signature = self.signature();
266
267        if signature.len() < 4 {
268            return Err(serde::de::Error::invalid_length(
269                signature.len(),
270                &">= 4 characters",
271            ));
272        }
273
274        // We can't get None here cause we already established there are at least 4 chars above
275        let bytes = signature.as_bytes();
276        let c = bytes.first().map(|b| *b as char).expect("empty signature");
277        if c != DICT_ENTRY_SIG_START_CHAR {
278            return Err(serde::de::Error::invalid_value(
279                serde::de::Unexpected::Char(c),
280                &crate::DICT_ENTRY_SIG_START_STR,
281            ));
282        }
283
284        let key_parser = self.slice(1..);
285        let key_signature = key_parser.next_signature()?;
286        // Key's signature will always be just 1 character.
287        if key_signature.len() != 1 {
288            return Err(serde::de::Error::invalid_length(
289                key_signature.len(),
290                &"dict-entry key's signature can only be a single character",
291            ));
292        }
293
294        // There should be one valid complete signature for value.
295        let value_parser = self.slice(2..);
296        let value_len = value_parser.next_signature()?.len();
297        // signature of value + `{` + 1 char of the key signature + `}`
298        let end = value_len + 3;
299
300        if signature.len() < end {
301            return Err(serde::de::Error::invalid_length(
302                signature.len(),
303                &format!(">= {end} characters").as_str(),
304            ));
305        }
306        if bytes[end - 1] as char != DICT_ENTRY_SIG_END_CHAR {
307            return Err(serde::de::Error::invalid_value(
308                serde::de::Unexpected::Char(c),
309                &crate::DICT_ENTRY_SIG_END_STR,
310            ));
311        }
312
313        Ok(self.signature_slice(0, end))
314    }
315
316    fn signature_slice(&self, idx: usize, end: usize) -> Signature<'_> {
317        self.signature.slice(self.pos + idx..self.pos + end)
318    }
319}
320
321impl<'a> Iterator for SignatureParser<'a> {
322    type Item = Result<Signature<'a>>;
323
324    fn next(&mut self) -> Option<Self::Item> {
325        if self.done() {
326            None
327        } else {
328            Some(self.parse_next_signature())
329        }
330    }
331}