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