| 1 | //! Utility functions for X11 things. |
| 2 | //! |
| 3 | //! The most important definitions in this module are the [`TryParse`], [`TryParseFd`] and |
| 4 | //! [`Serialize`] traits. These traits are used internally for parsing incoming data and producing |
| 5 | //! outgoing data when talking with the X11 server. |
| 6 | |
| 7 | use alloc::string::String; |
| 8 | use alloc::vec::Vec; |
| 9 | |
| 10 | use crate::errors::ParseError; |
| 11 | use crate::protocol::{request_name, ErrorKind}; |
| 12 | use crate::utils::RawFdContainer; |
| 13 | use crate::BufWithFds; |
| 14 | |
| 15 | /// Representation of an X11 error packet that was sent by the server. |
| 16 | #[derive (Debug, Clone, PartialEq, Eq)] |
| 17 | pub struct X11Error { |
| 18 | /// The kind of error that occurred. |
| 19 | pub error_kind: ErrorKind, |
| 20 | /// The kind of error that occurred as it appears "on the wire". |
| 21 | pub error_code: u8, |
| 22 | /// The sequence number of the request that caused this error. |
| 23 | pub sequence: u16, |
| 24 | /// The value in the request that caused the error. |
| 25 | pub bad_value: u32, |
| 26 | /// The minor opcode of the request that caused this error. |
| 27 | pub minor_opcode: u16, |
| 28 | /// The major opcode of the request that caused this error. |
| 29 | pub major_opcode: u8, |
| 30 | /// Name of the extension that caused this error, if known. |
| 31 | pub extension_name: Option<String>, |
| 32 | /// Name of the request that caused this error, if known. |
| 33 | pub request_name: Option<&'static str>, |
| 34 | } |
| 35 | |
| 36 | impl X11Error { |
| 37 | /// Parse an X11 error. |
| 38 | pub fn try_parse( |
| 39 | data: &[u8], |
| 40 | ext_info_provider: &dyn ExtInfoProvider, |
| 41 | ) -> Result<Self, ParseError> { |
| 42 | let (response_type, remaining) = u8::try_parse(data)?; |
| 43 | let (error_code, remaining) = u8::try_parse(remaining)?; |
| 44 | let (sequence, remaining) = u16::try_parse(remaining)?; |
| 45 | let (bad_value, remaining) = u32::try_parse(remaining)?; |
| 46 | let (minor_opcode, remaining) = u16::try_parse(remaining)?; |
| 47 | let (major_opcode, _) = u8::try_parse(remaining)?; |
| 48 | if response_type != 0 { |
| 49 | Err(ParseError::InvalidValue) |
| 50 | } else { |
| 51 | let error_kind = ErrorKind::from_wire_error_code(error_code, ext_info_provider); |
| 52 | let (extension_name, request_name) = |
| 53 | request_name(ext_info_provider, major_opcode, minor_opcode); |
| 54 | Ok(X11Error { |
| 55 | error_kind, |
| 56 | error_code, |
| 57 | sequence, |
| 58 | bad_value, |
| 59 | minor_opcode, |
| 60 | major_opcode, |
| 61 | extension_name, |
| 62 | request_name, |
| 63 | }) |
| 64 | } |
| 65 | } |
| 66 | } |
| 67 | |
| 68 | #[cfg (test)] |
| 69 | mod tryparse_x11error_test { |
| 70 | use super::{ErrorKind, ExtInfoProvider, ParseError, X11Error}; |
| 71 | use crate::x11_utils::ExtensionInformation; |
| 72 | |
| 73 | struct Provider; |
| 74 | |
| 75 | impl ExtInfoProvider for Provider { |
| 76 | fn get_from_major_opcode(&self, major_opcode: u8) -> Option<(&str, ExtensionInformation)> { |
| 77 | assert_eq!(major_opcode, 10); |
| 78 | None |
| 79 | } |
| 80 | fn get_from_event_code(&self, _event_code: u8) -> Option<(&str, ExtensionInformation)> { |
| 81 | unimplemented!() |
| 82 | } |
| 83 | fn get_from_error_code(&self, _error_code: u8) -> Option<(&str, ExtensionInformation)> { |
| 84 | unimplemented!() |
| 85 | } |
| 86 | } |
| 87 | |
| 88 | #[test ] |
| 89 | fn try_parse_error() { |
| 90 | let input = [ |
| 91 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 92 | 0, 0, 0, |
| 93 | ]; |
| 94 | let error = X11Error::try_parse(&input, &Provider); |
| 95 | let expected = X11Error { |
| 96 | error_kind: ErrorKind::Request, |
| 97 | error_code: 1, |
| 98 | sequence: u16::from_ne_bytes([2, 3]), |
| 99 | bad_value: u32::from_ne_bytes([4, 5, 6, 7]), |
| 100 | minor_opcode: u16::from_ne_bytes([8, 9]), |
| 101 | major_opcode: 10, |
| 102 | extension_name: None, |
| 103 | request_name: Some("UnmapWindow" ), |
| 104 | }; |
| 105 | assert_eq!(error, Ok(expected)); |
| 106 | } |
| 107 | |
| 108 | #[test ] |
| 109 | fn reject_invalid_response_type() { |
| 110 | let result = X11Error::try_parse(&[1; 32], &Provider); |
| 111 | assert_eq!(Err(ParseError::InvalidValue), result); |
| 112 | } |
| 113 | } |
| 114 | |
| 115 | impl From<&X11Error> for [u8; 32] { |
| 116 | fn from(input: &X11Error) -> Self { |
| 117 | let sequence_bytes = input.sequence.serialize(); |
| 118 | let bad_value_bytes = input.bad_value.serialize(); |
| 119 | let minor_opcode_bytes = input.minor_opcode.serialize(); |
| 120 | [ |
| 121 | 0, |
| 122 | input.error_code, |
| 123 | sequence_bytes[0], |
| 124 | sequence_bytes[1], |
| 125 | bad_value_bytes[0], |
| 126 | bad_value_bytes[1], |
| 127 | bad_value_bytes[2], |
| 128 | bad_value_bytes[3], |
| 129 | minor_opcode_bytes[0], |
| 130 | minor_opcode_bytes[1], |
| 131 | input.major_opcode, |
| 132 | 0, |
| 133 | 0, |
| 134 | 0, |
| 135 | 0, |
| 136 | 0, |
| 137 | 0, |
| 138 | 0, |
| 139 | 0, |
| 140 | 0, |
| 141 | 0, |
| 142 | 0, |
| 143 | 0, |
| 144 | 0, |
| 145 | 0, |
| 146 | 0, |
| 147 | 0, |
| 148 | 0, |
| 149 | 0, |
| 150 | 0, |
| 151 | 0, |
| 152 | 0, |
| 153 | ] |
| 154 | } |
| 155 | } |
| 156 | impl From<X11Error> for [u8; 32] { |
| 157 | fn from(input: X11Error) -> Self { |
| 158 | Self::from(&input) |
| 159 | } |
| 160 | } |
| 161 | |
| 162 | #[cfg (test)] |
| 163 | mod serialise_x11error_test { |
| 164 | use super::{ErrorKind, X11Error}; |
| 165 | |
| 166 | #[test ] |
| 167 | fn test_serialise() { |
| 168 | let error = X11Error { |
| 169 | error_kind: ErrorKind::Request, |
| 170 | error_code: 1, |
| 171 | sequence: u16::from_ne_bytes([2, 3]), |
| 172 | bad_value: u32::from_ne_bytes([4, 5, 6, 7]), |
| 173 | minor_opcode: u16::from_ne_bytes([8, 9]), |
| 174 | major_opcode: 10, |
| 175 | extension_name: None, |
| 176 | request_name: None, |
| 177 | }; |
| 178 | let expected = [ |
| 179 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 180 | 0, 0, 0, |
| 181 | ]; |
| 182 | assert_eq!(expected, <[u8; 32]>::from(error)); |
| 183 | } |
| 184 | } |
| 185 | |
| 186 | /// Information about a X11 extension. |
| 187 | #[derive (Debug, Copy, Clone, PartialEq, Eq)] |
| 188 | pub struct ExtensionInformation { |
| 189 | /// Major opcode used in request |
| 190 | pub major_opcode: u8, |
| 191 | /// Lowest event number used by the extension. |
| 192 | pub first_event: u8, |
| 193 | /// Lowest error number used by the extension. |
| 194 | pub first_error: u8, |
| 195 | } |
| 196 | |
| 197 | /// Trait to provide information about extensions. |
| 198 | pub trait ExtInfoProvider { |
| 199 | /// Returns the information of the extension that whose |
| 200 | /// opcode is `major_opcode`. |
| 201 | fn get_from_major_opcode(&self, major_opcode: u8) -> Option<(&str, ExtensionInformation)>; |
| 202 | |
| 203 | /// Returns the information of the extension that whose |
| 204 | /// event number range includes `event_number`. |
| 205 | fn get_from_event_code(&self, event_code: u8) -> Option<(&str, ExtensionInformation)>; |
| 206 | |
| 207 | /// Returns the information of the extension that whose |
| 208 | /// error number range includes `error_number`. |
| 209 | fn get_from_error_code(&self, error_code: u8) -> Option<(&str, ExtensionInformation)>; |
| 210 | } |
| 211 | |
| 212 | /// A type implementing this trait can be parsed from some raw bytes. |
| 213 | pub trait TryParse: Sized { |
| 214 | /// Try to parse the given values into an instance of this type. |
| 215 | /// |
| 216 | /// If parsing is successful, an instance of the type and a slice for the remaining data should |
| 217 | /// be returned. Otherwise, an error is returned. |
| 218 | fn try_parse(value: &[u8]) -> Result<(Self, &[u8]), ParseError>; |
| 219 | } |
| 220 | |
| 221 | /// A type implementing this trait can be parsed from some raw bytes and a list of fds. |
| 222 | pub trait TryParseFd: Sized { |
| 223 | /// Try to parse the given values into an instance of this type. |
| 224 | /// |
| 225 | /// File descriptors are consumed by removing them from the beginning of the given `fds` `Vec`. |
| 226 | /// If a file descriptor is expected, but missing, a `ParseError` should be returned. If more file |
| 227 | /// descriptors are provided than expected, this is not an error and the remaining descriptors |
| 228 | /// should be left in the `Vec`. |
| 229 | /// |
| 230 | /// If parsing is successful, an instance of the type and a slice for the remaining data should |
| 231 | /// be returned. Otherwise, an error is returned. |
| 232 | fn try_parse_fd<'a>( |
| 233 | value: &'a [u8], |
| 234 | fds: &mut Vec<RawFdContainer>, |
| 235 | ) -> Result<(Self, &'a [u8]), ParseError>; |
| 236 | } |
| 237 | |
| 238 | impl<T: TryParse> TryParseFd for T { |
| 239 | fn try_parse_fd<'a>( |
| 240 | value: &'a [u8], |
| 241 | _: &mut Vec<RawFdContainer>, |
| 242 | ) -> Result<(Self, &'a [u8]), ParseError> { |
| 243 | T::try_parse(value) |
| 244 | } |
| 245 | } |
| 246 | |
| 247 | /// A representation of the header of a request. |
| 248 | #[derive (Debug, Clone, Copy)] |
| 249 | pub struct RequestHeader { |
| 250 | /// The major opcode of the request. |
| 251 | pub major_opcode: u8, |
| 252 | /// The minor opcode of the request (which, for some requests, may not be an |
| 253 | /// opcode at all). |
| 254 | pub minor_opcode: u8, |
| 255 | /// The remaining length of the request, measured in 4 bytes units. Unlike the wire format, |
| 256 | /// this does *not* include the header itself, which is 1 unit (or 2 if BigRequests is |
| 257 | /// enabled and the length in the first unit is zero). If the BigRequests extension is |
| 258 | /// enabled this can be greater than u16::max_value - 1. |
| 259 | pub remaining_length: u32, |
| 260 | } |
| 261 | |
| 262 | /// A type implementing this trait is an X11 request. |
| 263 | pub trait Request { |
| 264 | /// The protocol name of the extension that this request belongs to, or None for core requests |
| 265 | const EXTENSION_NAME: Option<&'static str>; |
| 266 | |
| 267 | /// Serialize this request into its X11 protocol wire representation. |
| 268 | /// |
| 269 | /// The argument is the major opcode of the extension that this request belongs to. For core |
| 270 | /// requests, the argument may not have any influence |
| 271 | fn serialize(self, extension_opcode: u8) -> BufWithFds<Vec<u8>>; |
| 272 | } |
| 273 | |
| 274 | /// A type alias for reply parsers (matches the signature of TryParseFd). |
| 275 | pub type ReplyParsingFunction = |
| 276 | for<'a> fn( |
| 277 | &'a [u8], |
| 278 | &mut Vec<RawFdContainer>, |
| 279 | ) -> Result<(crate::protocol::Reply, &'a [u8]), ParseError>; |
| 280 | |
| 281 | /// A X11 request that does not have a reply |
| 282 | pub trait VoidRequest: Request {} |
| 283 | |
| 284 | /// A X11 request that has a reply without FDs |
| 285 | pub trait ReplyRequest: Request { |
| 286 | /// The kind of reply that this request generates. |
| 287 | type Reply: Into<crate::protocol::Reply> + TryParse; |
| 288 | } |
| 289 | |
| 290 | /// A X11 request that has a reply with FDs |
| 291 | pub trait ReplyFDsRequest: Request { |
| 292 | /// The kind of reply that this request generates. |
| 293 | type Reply: Into<crate::protocol::Reply> + TryParseFd; |
| 294 | } |
| 295 | |
| 296 | /// A type implementing this trait can be serialized into X11 raw bytes. |
| 297 | pub trait Serialize { |
| 298 | /// The value returned by `serialize`. |
| 299 | /// |
| 300 | /// This should be `Vec<u8>` in most cases. However, arrays like `[u8; 4]` should also be |
| 301 | /// allowed and thus this is an associated type. |
| 302 | /// |
| 303 | /// If generic associated types were available, implementing `AsRef<[u8]>` would be required. |
| 304 | type Bytes; |
| 305 | |
| 306 | /// Serialize this value into X11 raw bytes. |
| 307 | fn serialize(&self) -> Self::Bytes; |
| 308 | |
| 309 | /// Serialize this value into X11 raw bytes, appending the result into `bytes`. |
| 310 | /// |
| 311 | /// When calling this method, the given vector must satisfy `assert_eq!(bytes.len() % 4, 0);`. |
| 312 | /// In words: Its length must be a multiple of four. |
| 313 | fn serialize_into(&self, bytes: &mut Vec<u8>); |
| 314 | } |
| 315 | |
| 316 | // Now implement TryParse and Serialize for some primitive data types that we need. |
| 317 | |
| 318 | macro_rules! implement_try_parse { |
| 319 | ($t:ty) => { |
| 320 | impl TryParse for $t { |
| 321 | fn try_parse(value: &[u8]) -> Result<(Self, &[u8]), ParseError> { |
| 322 | let len = core::mem::size_of::<$t>(); |
| 323 | let bytes = value |
| 324 | .get(..len) |
| 325 | .ok_or(ParseError::InsufficientData)? |
| 326 | .try_into() // TryInto<[u8; len]> |
| 327 | .unwrap(); |
| 328 | Ok((<$t>::from_ne_bytes(bytes), &value[len..])) |
| 329 | } |
| 330 | } |
| 331 | }; |
| 332 | } |
| 333 | |
| 334 | macro_rules! implement_serialize { |
| 335 | ($t:ty: $size:expr) => { |
| 336 | impl Serialize for $t { |
| 337 | type Bytes = [u8; $size]; |
| 338 | fn serialize(&self) -> Self::Bytes { |
| 339 | self.to_ne_bytes() |
| 340 | } |
| 341 | fn serialize_into(&self, bytes: &mut Vec<u8>) { |
| 342 | bytes.extend_from_slice(&self.to_ne_bytes()); |
| 343 | } |
| 344 | } |
| 345 | }; |
| 346 | } |
| 347 | |
| 348 | macro_rules! forward_float { |
| 349 | ($from:ty: $to:ty) => { |
| 350 | impl TryParse for $from { |
| 351 | fn try_parse(value: &[u8]) -> Result<(Self, &[u8]), ParseError> { |
| 352 | let (data, remaining) = <$to>::try_parse(value)?; |
| 353 | Ok((<$from>::from_bits(data), remaining)) |
| 354 | } |
| 355 | } |
| 356 | impl Serialize for $from { |
| 357 | type Bytes = <$to as Serialize>::Bytes; |
| 358 | fn serialize(&self) -> Self::Bytes { |
| 359 | self.to_bits().serialize() |
| 360 | } |
| 361 | fn serialize_into(&self, bytes: &mut Vec<u8>) { |
| 362 | self.to_bits().serialize_into(bytes); |
| 363 | } |
| 364 | } |
| 365 | }; |
| 366 | } |
| 367 | |
| 368 | implement_try_parse!(u8); |
| 369 | implement_try_parse!(i8); |
| 370 | implement_try_parse!(u16); |
| 371 | implement_try_parse!(i16); |
| 372 | implement_try_parse!(u32); |
| 373 | implement_try_parse!(i32); |
| 374 | implement_try_parse!(u64); |
| 375 | implement_try_parse!(i64); |
| 376 | |
| 377 | implement_serialize!(u8: 1); |
| 378 | implement_serialize!(i8: 1); |
| 379 | implement_serialize!(u16: 2); |
| 380 | implement_serialize!(i16: 2); |
| 381 | implement_serialize!(u32: 4); |
| 382 | implement_serialize!(i32: 4); |
| 383 | implement_serialize!(u64: 8); |
| 384 | implement_serialize!(i64: 8); |
| 385 | |
| 386 | forward_float!(f32: u32); |
| 387 | forward_float!(f64: u64); |
| 388 | |
| 389 | #[cfg (test)] |
| 390 | mod float_tests { |
| 391 | use super::{Serialize, TryParse}; |
| 392 | |
| 393 | fn test_round_trip<F>(value: F) |
| 394 | where |
| 395 | F: TryParse + Serialize + PartialEq + core::fmt::Debug + Copy, |
| 396 | <F as Serialize>::Bytes: AsRef<[u8]>, |
| 397 | { |
| 398 | let empty = &[][..]; |
| 399 | |
| 400 | // Test using serialize() |
| 401 | assert_eq!(Ok((value, empty)), F::try_parse(value.serialize().as_ref())); |
| 402 | |
| 403 | // Test using serialize_into() |
| 404 | let mut output = alloc::vec::Vec::new(); |
| 405 | value.serialize_into(&mut output); |
| 406 | assert_eq!(Ok((value, empty)), F::try_parse(&output)); |
| 407 | } |
| 408 | |
| 409 | #[test ] |
| 410 | fn test_f32_round_trips() { |
| 411 | for &f in &[0f32, 1., std::f32::consts::PI, 42., 1337., 1e7] { |
| 412 | test_round_trip(f); |
| 413 | test_round_trip(-f); |
| 414 | } |
| 415 | } |
| 416 | |
| 417 | #[test ] |
| 418 | fn test_f64_round_trips() { |
| 419 | for &f in &[0f64, 1., std::f64::consts::PI, 42., 1337., 1e7] { |
| 420 | test_round_trip(f); |
| 421 | test_round_trip(-f); |
| 422 | } |
| 423 | } |
| 424 | |
| 425 | #[test ] |
| 426 | fn test_parse_known_value() { |
| 427 | let bytes = 0x42280000u32.to_ne_bytes(); |
| 428 | let value = f32::try_parse(&bytes); |
| 429 | let empty = &[][..]; |
| 430 | assert_eq!(Ok((42., empty)), value); |
| 431 | } |
| 432 | |
| 433 | #[test ] |
| 434 | fn test_serialize_known_value() { |
| 435 | assert_eq!(0x42280000u32.to_ne_bytes(), 42f32.serialize()); |
| 436 | } |
| 437 | } |
| 438 | |
| 439 | impl TryParse for bool { |
| 440 | fn try_parse(value: &[u8]) -> Result<(Self, &[u8]), ParseError> { |
| 441 | let (data: u8, remaining: &[u8]) = u8::try_parse(value)?; |
| 442 | Ok((data != 0, remaining)) |
| 443 | } |
| 444 | } |
| 445 | |
| 446 | impl Serialize for bool { |
| 447 | type Bytes = [u8; 1]; |
| 448 | fn serialize(&self) -> Self::Bytes { |
| 449 | [u8::from(*self)] |
| 450 | } |
| 451 | fn serialize_into(&self, bytes: &mut Vec<u8>) { |
| 452 | bytes.push(u8::from(*self)); |
| 453 | } |
| 454 | } |
| 455 | |
| 456 | // Tuple handling |
| 457 | |
| 458 | macro_rules! tuple_try_parse { |
| 459 | ($($name:ident)*) => { |
| 460 | impl<$($name,)*> TryParse for ($($name,)*) |
| 461 | where $($name: TryParse,)* |
| 462 | { |
| 463 | #[allow(non_snake_case)] |
| 464 | fn try_parse(remaining: &[u8]) -> Result<(($($name,)*), &[u8]), ParseError> { |
| 465 | $(let ($name, remaining) = $name::try_parse(remaining)?;)* |
| 466 | Ok((($($name,)*), remaining)) |
| 467 | } |
| 468 | } |
| 469 | } |
| 470 | } |
| 471 | |
| 472 | macro_rules! tuple_serialize { |
| 473 | ($($name:ident:$idx:tt)*) => { |
| 474 | impl<$($name,)*> Serialize for ($($name,)*) |
| 475 | where $($name: Serialize,)* |
| 476 | { |
| 477 | type Bytes = Vec<u8>; |
| 478 | fn serialize(&self) -> Self::Bytes { |
| 479 | let mut result = Vec::new(); |
| 480 | self.serialize_into(&mut result); |
| 481 | result |
| 482 | } |
| 483 | fn serialize_into(&self, bytes: &mut Vec<u8>) { |
| 484 | $(self.$idx.serialize_into(bytes);)* |
| 485 | } |
| 486 | } |
| 487 | } |
| 488 | } |
| 489 | |
| 490 | macro_rules! tuple_impls { |
| 491 | ($($name:ident:$idx:tt)*) => { |
| 492 | tuple_try_parse!($($name)*); |
| 493 | tuple_serialize!($($name:$idx)*); |
| 494 | } |
| 495 | } |
| 496 | |
| 497 | // We can optimise serialisation of empty tuples or one-element-tuples with different Bytes type |
| 498 | impl Serialize for () { |
| 499 | type Bytes = [u8; 0]; |
| 500 | fn serialize(&self) -> Self::Bytes { |
| 501 | [] |
| 502 | } |
| 503 | fn serialize_into(&self, _bytes: &mut Vec<u8>) {} |
| 504 | } |
| 505 | |
| 506 | impl<T: Serialize> Serialize for (T,) { |
| 507 | type Bytes = T::Bytes; |
| 508 | fn serialize(&self) -> Self::Bytes { |
| 509 | self.0.serialize() |
| 510 | } |
| 511 | fn serialize_into(&self, bytes: &mut Vec<u8>) { |
| 512 | self.0.serialize_into(bytes) |
| 513 | } |
| 514 | } |
| 515 | |
| 516 | tuple_try_parse!(); |
| 517 | tuple_try_parse!(A); |
| 518 | tuple_impls!(A:0 B:1); |
| 519 | tuple_impls!(A:0 B:1 C:2); |
| 520 | tuple_impls!(A:0 B:1 C:2 D:3); |
| 521 | tuple_impls!(A:0 B:1 C:2 D:3 E:4); |
| 522 | tuple_impls!(A:0 B:1 C:2 D:3 E:4 F:5); |
| 523 | tuple_impls!(A:0 B:1 C:2 D:3 E:4 F:5 G:6); |
| 524 | tuple_impls!(A:0 B:1 C:2 D:3 E:4 F:5 G:6 H:7); |
| 525 | tuple_impls!(A:0 B:1 C:2 D:3 E:4 F:5 G:6 H:7 I:8); |
| 526 | tuple_impls!(A:0 B:1 C:2 D:3 E:4 F:5 G:6 H:7 I:8 J:9); |
| 527 | tuple_impls!(A:0 B:1 C:2 D:3 E:4 F:5 G:6 H:7 I:8 J:9 K:10); |
| 528 | tuple_impls!(A:0 B:1 C:2 D:3 E:4 F:5 G:6 H:7 I:8 J:9 K:10 L:11); |
| 529 | tuple_impls!(A:0 B:1 C:2 D:3 E:4 F:5 G:6 H:7 I:8 J:9 K:10 L:11 M:12); |
| 530 | tuple_impls!(A:0 B:1 C:2 D:3 E:4 F:5 G:6 H:7 I:8 J:9 K:10 L:11 M:12 N:13); |
| 531 | tuple_impls!(A:0 B:1 C:2 D:3 E:4 F:5 G:6 H:7 I:8 J:9 K:10 L:11 M:12 N:13 O:14); |
| 532 | |
| 533 | /// Parse a list of objects from the given data. |
| 534 | /// |
| 535 | /// This function parses a list of objects where the length of the list was specified externally. |
| 536 | /// The wire format for `list_length` instances of `T` will be read from the given data. |
| 537 | pub(crate) fn parse_list<T>(data: &[u8], list_length: usize) -> Result<(Vec<T>, &[u8]), ParseError> |
| 538 | where |
| 539 | T: TryParse, |
| 540 | { |
| 541 | let mut remaining: &[u8] = data; |
| 542 | let mut result: Vec = Vec::with_capacity(list_length); |
| 543 | for _ in 0..list_length { |
| 544 | let (entry: T, new_remaining: &[u8]) = T::try_parse(remaining)?; |
| 545 | result.push(entry); |
| 546 | remaining = new_remaining; |
| 547 | } |
| 548 | Ok((result, remaining)) |
| 549 | } |
| 550 | |
| 551 | /// Parse a list of `u8` from the given data. |
| 552 | #[inline ] |
| 553 | pub(crate) fn parse_u8_list(data: &[u8], list_length: usize) -> Result<(&[u8], &[u8]), ParseError> { |
| 554 | if data.len() < list_length { |
| 555 | Err(ParseError::InsufficientData) |
| 556 | } else { |
| 557 | Ok(data.split_at(mid:list_length)) |
| 558 | } |
| 559 | } |
| 560 | |
| 561 | /// Parse an array of `u8` from the given data. |
| 562 | #[inline ] |
| 563 | pub(crate) fn parse_u8_array_ref<const N: usize>( |
| 564 | data: &[u8], |
| 565 | ) -> Result<(&[u8; N], &[u8]), ParseError> { |
| 566 | let (slice: &[u8], remaining: &[u8]) = parse_u8_list(data, N)?; |
| 567 | let slice: &[u8; N] = slice |
| 568 | .try_into() |
| 569 | .expect(msg:"Cannot fail since slice has expected length" ); |
| 570 | Ok((slice, remaining)) |
| 571 | } |
| 572 | |
| 573 | /// Parse an array of `u8` from the given data. |
| 574 | #[inline ] |
| 575 | pub(crate) fn parse_u8_array<const N: usize>(data: &[u8]) -> Result<([u8; N], &[u8]), ParseError> { |
| 576 | let (array: &[u8; N], remaining: &[u8]) = parse_u8_array_ref(data)?; |
| 577 | Ok((*array, remaining)) |
| 578 | } |
| 579 | |
| 580 | impl<T: Serialize> Serialize for [T] { |
| 581 | type Bytes = Vec<u8>; |
| 582 | fn serialize(&self) -> Self::Bytes { |
| 583 | let mut result: Vec = Vec::new(); |
| 584 | self.serialize_into(&mut result); |
| 585 | result |
| 586 | } |
| 587 | fn serialize_into(&self, bytes: &mut Vec<u8>) { |
| 588 | for item: &T in self { |
| 589 | item.serialize_into(bytes); |
| 590 | } |
| 591 | } |
| 592 | } |
| 593 | |
| 594 | // This macro is used by the generated code to implement e.g. `std::ops::BitOr` and |
| 595 | // `std::ops::BitOrAssign`. |
| 596 | macro_rules! bitmask_binop { |
| 597 | ($t:ty, $u:ty) => { |
| 598 | impl core::ops::BitOr for $t { |
| 599 | type Output = $t; |
| 600 | fn bitor(self, other: Self) -> Self::Output { |
| 601 | Self::from(<$u>::from(self) | <$u>::from(other)) |
| 602 | } |
| 603 | } |
| 604 | impl core::ops::BitOr<$u> for $t { |
| 605 | type Output = $t; |
| 606 | fn bitor(self, other: $u) -> Self::Output { |
| 607 | self | Self::from(other) |
| 608 | } |
| 609 | } |
| 610 | impl core::ops::BitOr<$t> for $u { |
| 611 | type Output = $t; |
| 612 | fn bitor(self, other: $t) -> Self::Output { |
| 613 | <$t>::from(self) | other |
| 614 | } |
| 615 | } |
| 616 | impl core::ops::BitOrAssign for $t { |
| 617 | fn bitor_assign(&mut self, other: $t) { |
| 618 | *self = *self | Self::from(other) |
| 619 | } |
| 620 | } |
| 621 | impl core::ops::BitOrAssign<$t> for $u { |
| 622 | fn bitor_assign(&mut self, other: $t) { |
| 623 | *self |= Self::from(other) |
| 624 | } |
| 625 | } |
| 626 | impl core::ops::BitOrAssign<$u> for $t { |
| 627 | fn bitor_assign(&mut self, other: $u) { |
| 628 | self.0 |= other |
| 629 | } |
| 630 | } |
| 631 | impl core::ops::BitAnd for $t { |
| 632 | type Output = $t; |
| 633 | fn bitand(self, other: Self) -> Self::Output { |
| 634 | Self::from(<$u>::from(self) & <$u>::from(other)) |
| 635 | } |
| 636 | } |
| 637 | impl core::ops::BitAnd<$u> for $t { |
| 638 | type Output = $t; |
| 639 | fn bitand(self, other: $u) -> Self::Output { |
| 640 | self & Self::from(other) |
| 641 | } |
| 642 | } |
| 643 | impl core::ops::BitAnd<$t> for $u { |
| 644 | type Output = $t; |
| 645 | fn bitand(self, other: $t) -> Self::Output { |
| 646 | <$t>::from(self) & other |
| 647 | } |
| 648 | } |
| 649 | impl core::ops::BitAndAssign for $t { |
| 650 | fn bitand_assign(&mut self, other: $t) { |
| 651 | self.0 &= other |
| 652 | } |
| 653 | } |
| 654 | impl core::ops::BitAndAssign<$t> for $u { |
| 655 | fn bitand_assign(&mut self, other: $t) { |
| 656 | *self &= Self::from(other) |
| 657 | } |
| 658 | } |
| 659 | impl core::ops::BitAndAssign<$u> for $t { |
| 660 | fn bitand_assign(&mut self, other: $u) { |
| 661 | self.0 &= other |
| 662 | } |
| 663 | } |
| 664 | impl $t { |
| 665 | /// Check if this object has all bits set that are also set in `flag`. |
| 666 | /// |
| 667 | /// `flag` can be a single enum variant or a whole other mask. |
| 668 | pub fn contains(self, flag: impl Into<$u>) -> bool { |
| 669 | let flag = flag.into(); |
| 670 | (<$u>::from(self) & flag) == flag |
| 671 | } |
| 672 | |
| 673 | /// Check if this object has some bits set that are also set in `flag`. |
| 674 | /// |
| 675 | /// `flag` can be a single enum variant or a whole other mask. |
| 676 | pub fn intersects(self, flag: impl Into<$u>) -> bool { |
| 677 | let flag = flag.into(); |
| 678 | (<$u>::from(self) & flag) != 0 |
| 679 | } |
| 680 | |
| 681 | /// Remove some flags. |
| 682 | /// |
| 683 | /// All bits that are set in the given flags are removed from the `self` instance, if |
| 684 | /// they are present. |
| 685 | pub fn remove(self, flags: impl Into<$u>) -> Self { |
| 686 | Self::from(self.bits() & !flags.into()) |
| 687 | } |
| 688 | |
| 689 | /// Returns the internal value of the object. |
| 690 | pub fn bits(self) -> $u { |
| 691 | self.0 |
| 692 | } |
| 693 | } |
| 694 | }; |
| 695 | } |
| 696 | |
| 697 | macro_rules! impl_debug_if_no_extra_traits { |
| 698 | ($type:ty, $name:literal) => { |
| 699 | #[cfg(not(feature = "extra-traits" ))] |
| 700 | impl core::fmt::Debug for $type { |
| 701 | fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { |
| 702 | f.debug_struct($name).finish_non_exhaustive() |
| 703 | } |
| 704 | } |
| 705 | }; |
| 706 | } |
| 707 | |
| 708 | /// Wrapper around TryInto that produces a ParseError. |
| 709 | /// |
| 710 | /// This trait shortens `x.try_into().or(Err(ParseError::ConversionFailed))` to `x.try_to_usize()`. |
| 711 | pub(crate) trait TryIntoUSize: TryInto<usize> { |
| 712 | /// Attempt the conversion |
| 713 | fn try_to_usize(self) -> Result<usize, ParseError> { |
| 714 | self.try_into().or(res:Err(ParseError::ConversionFailed)) |
| 715 | } |
| 716 | } |
| 717 | |
| 718 | impl TryIntoUSize for u8 {} |
| 719 | impl TryIntoUSize for u16 {} |
| 720 | impl TryIntoUSize for u32 {} |
| 721 | impl TryIntoUSize for u64 {} |
| 722 | impl TryIntoUSize for i8 {} |
| 723 | impl TryIntoUSize for i16 {} |
| 724 | impl TryIntoUSize for i32 {} |
| 725 | impl TryIntoUSize for i64 {} |
| 726 | |
| 727 | /// Has the BigRequests extension been enabled? |
| 728 | #[derive (Debug, Clone, Copy, PartialEq, Eq)] |
| 729 | pub enum BigRequests { |
| 730 | /// The BigRequests extension has been enabled. |
| 731 | Enabled, |
| 732 | /// The BigRequests extension has not been enabled. |
| 733 | NotEnabled, |
| 734 | } |
| 735 | |
| 736 | /// Parse the given input for a RequestHeader and the remaining input. |
| 737 | pub fn parse_request_header( |
| 738 | input: &[u8], |
| 739 | big_requests_enabled: BigRequests, |
| 740 | ) -> Result<(RequestHeader, &[u8]), ParseError> { |
| 741 | let (major_opcode, remaining) = u8::try_parse(input)?; |
| 742 | let (minor_opcode, remaining) = u8::try_parse(remaining)?; |
| 743 | let (length, remaining) = u16::try_parse(remaining)?; |
| 744 | let (remaining_length, finally_remaining) = if length == 0 { |
| 745 | if big_requests_enabled == BigRequests::NotEnabled { |
| 746 | return Err(ParseError::InvalidValue); |
| 747 | } |
| 748 | |
| 749 | let (length, remaining) = u32::try_parse(remaining)?; |
| 750 | if length < 2 { |
| 751 | return Err(ParseError::InvalidValue); |
| 752 | } |
| 753 | // Adjust length for the size of this header (two 4 byte units). |
| 754 | (length - 2, remaining) |
| 755 | } else { |
| 756 | // Adjust length for the size of this header (one 4 byte unit). |
| 757 | (u32::from(length) - 1, remaining) |
| 758 | }; |
| 759 | Ok(( |
| 760 | RequestHeader { |
| 761 | major_opcode, |
| 762 | minor_opcode, |
| 763 | remaining_length, |
| 764 | }, |
| 765 | finally_remaining, |
| 766 | )) |
| 767 | } |
| 768 | |