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
7use alloc::string::String;
8use alloc::vec::Vec;
9
10use crate::errors::ParseError;
11use crate::protocol::{request_name, ErrorKind};
12use crate::utils::RawFdContainer;
13use crate::BufWithFds;
14
15/// Representation of an X11 error packet that was sent by the server.
16#[derive(Debug, Clone, PartialEq, Eq)]
17pub 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
36impl 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)]
69mod 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
115impl 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}
156impl From<X11Error> for [u8; 32] {
157 fn from(input: X11Error) -> Self {
158 Self::from(&input)
159 }
160}
161
162#[cfg(test)]
163mod 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)]
188pub 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.
198pub 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.
213pub 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.
222pub 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
238impl<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)]
249pub 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.
263pub 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).
275pub 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
282pub trait VoidRequest: Request {}
283
284/// A X11 request that has a reply without FDs
285pub 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
291pub 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.
297pub 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
318macro_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
334macro_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
348macro_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
368implement_try_parse!(u8);
369implement_try_parse!(i8);
370implement_try_parse!(u16);
371implement_try_parse!(i16);
372implement_try_parse!(u32);
373implement_try_parse!(i32);
374implement_try_parse!(u64);
375implement_try_parse!(i64);
376
377implement_serialize!(u8: 1);
378implement_serialize!(i8: 1);
379implement_serialize!(u16: 2);
380implement_serialize!(i16: 2);
381implement_serialize!(u32: 4);
382implement_serialize!(i32: 4);
383implement_serialize!(u64: 8);
384implement_serialize!(i64: 8);
385
386forward_float!(f32: u32);
387forward_float!(f64: u64);
388
389#[cfg(test)]
390mod 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
439impl 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
446impl 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
458macro_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
472macro_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
490macro_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
498impl 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
506impl<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
516tuple_try_parse!();
517tuple_try_parse!(A);
518tuple_impls!(A:0 B:1);
519tuple_impls!(A:0 B:1 C:2);
520tuple_impls!(A:0 B:1 C:2 D:3);
521tuple_impls!(A:0 B:1 C:2 D:3 E:4);
522tuple_impls!(A:0 B:1 C:2 D:3 E:4 F:5);
523tuple_impls!(A:0 B:1 C:2 D:3 E:4 F:5 G:6);
524tuple_impls!(A:0 B:1 C:2 D:3 E:4 F:5 G:6 H:7);
525tuple_impls!(A:0 B:1 C:2 D:3 E:4 F:5 G:6 H:7 I:8);
526tuple_impls!(A:0 B:1 C:2 D:3 E:4 F:5 G:6 H:7 I:8 J:9);
527tuple_impls!(A:0 B:1 C:2 D:3 E:4 F:5 G:6 H:7 I:8 J:9 K:10);
528tuple_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);
529tuple_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);
530tuple_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);
531tuple_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.
537pub(crate) fn parse_list<T>(data: &[u8], list_length: usize) -> Result<(Vec<T>, &[u8]), ParseError>
538where
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]
553pub(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]
563pub(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]
575pub(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
580impl<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`.
596macro_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
697macro_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()`.
711pub(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
718impl TryIntoUSize for u8 {}
719impl TryIntoUSize for u16 {}
720impl TryIntoUSize for u32 {}
721impl TryIntoUSize for u64 {}
722impl TryIntoUSize for i8 {}
723impl TryIntoUSize for i16 {}
724impl TryIntoUSize for i32 {}
725impl TryIntoUSize for i64 {}
726
727/// Has the BigRequests extension been enabled?
728#[derive(Debug, Clone, Copy, PartialEq, Eq)]
729pub 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.
737pub 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