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