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 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 | |