1 | use std::ops::{Bound, RangeBounds}; |
2 | |
3 | use crate::{subslice, Basic, ObjectPath, Result, Signature, STRUCT_SIG_END_CHAR}; |
4 | |
5 | #[cfg (unix)] |
6 | use crate::Fd; |
7 | |
8 | #[cfg (feature = "gvariant" )] |
9 | use crate::utils::MAYBE_SIGNATURE_CHAR; |
10 | use 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)] |
16 | pub(crate) struct SignatureParser<'s> { |
17 | signature: Signature<'s>, |
18 | pos: usize, |
19 | end: usize, |
20 | } |
21 | |
22 | impl<'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 | |
321 | impl<'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 | } |
332 | |