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