x11rb_protocol/
x11_utils.rs

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, remaining) = 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 = data;
542    let mut result = Vec::with_capacity(list_length);
543    for _ in 0..list_length {
544        let (entry, new_remaining) = 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(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, remaining) = parse_u8_list(data, N)?;
567    let slice = slice
568        .try_into()
569        .expect("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, remaining) = 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::new();
584        self.serialize_into(&mut result);
585        result
586    }
587    fn serialize_into(&self, bytes: &mut Vec<u8>) {
588        for item 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(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}