runa_wayland_scanner/
lib.rs

1#[doc(inline)]
2pub use codegen::generate_protocol;
3#[doc(inline)]
4pub use macros::generate_protocol;
5
6#[derive(thiserror::Error, Debug)]
7pub enum Error {
8    #[error("{0}")]
9    Io(#[from] std::io::Error),
10    #[error("Unknown opcode {0}")]
11    UnknownOpcode(u32),
12}
13
14pub mod io {
15    use std::os::unix::io::RawFd;
16
17    pub use futures_lite::AsyncBufRead;
18    pub use runa_io_traits::*;
19    #[inline]
20    pub fn pop_fd(fds: &mut &[RawFd]) -> RawFd {
21        assert!(!fds.is_empty(), "Not enough fds in buffer");
22        // Safety: we checked that the slice is long enough
23        let ret = unsafe { *fds.get_unchecked(0) };
24        *fds = &fds[1..];
25        ret
26    }
27
28    #[inline]
29    /// Pop `len` bytes from the buffer and returns it. Advances the buffer by
30    /// `len` aligned up to 4 bytes.
31    pub fn pop_bytes<'a>(bytes: &mut &'a [u8], len: usize) -> &'a [u8] {
32        use std::slice::from_raw_parts;
33        let blen = bytes.len();
34        let len_aligned = (len + 3) & !3;
35        assert!(
36            blen >= len_aligned,
37            "Not enough bytes in buffer, has {blen}, asking for {len_aligned}"
38        );
39        let ptr = bytes.as_ptr();
40        // Safety: we checked that the slice is long enough
41        let (ret, rest) = unsafe {
42            (
43                from_raw_parts(ptr, len),
44                from_raw_parts(ptr.add(len_aligned), blen - len_aligned),
45            )
46        };
47        *bytes = rest;
48        ret
49    }
50
51    #[inline]
52    pub fn pop_i32(bytes: &mut &[u8]) -> i32 {
53        let slice = pop_bytes(bytes, 4);
54        // Safety: slice is guaranteed to be 4 bytes long
55        i32::from_ne_bytes(unsafe { *(slice.as_ptr() as *const [u8; 4]) })
56    }
57
58    #[inline]
59    pub fn pop_u32(bytes: &mut &[u8]) -> u32 {
60        let slice = pop_bytes(bytes, 4);
61        // Safety: slice is guaranteed to be 4 bytes long
62        u32::from_ne_bytes(unsafe { *(slice.as_ptr() as *const [u8; 4]) })
63    }
64}
65
66pub use bitflags::bitflags;
67pub use bytes::{BufMut, BytesMut};
68pub use futures_lite::ready;
69pub use num_enum;
70pub use runa_wayland_types as types;
71
72pub mod future {
73    use std::{pin::Pin, task::Poll};
74    pub struct PollMapFn<'a, F, O, T> {
75        inner:   Option<Pin<&'a mut T>>,
76        f:       F,
77        _marker: ::std::marker::PhantomData<O>,
78    }
79    impl<'a, F, O, T> ::std::future::Future for PollMapFn<'a, F, O, T>
80    where
81        F: Fn(Pin<&'a mut T>, &mut ::std::task::Context<'_>) -> Poll<O> + Unpin,
82        O: Unpin,
83    {
84        type Output = O;
85
86        fn poll(
87            mut self: ::std::pin::Pin<&mut Self>,
88            cx: &mut ::std::task::Context<'_>,
89        ) -> ::std::task::Poll<Self::Output> {
90            use std::ptr::NonNull;
91            let inner = self
92                .inner
93                .take()
94                .expect("PollMapFn polled after completion");
95            unsafe {
96                // Safety:
97                // 1. We don't move the reader using the &mut we get from
98                // Pin::get_mut_unchecked. 2. We know Fn(Pin<&'de mut D>, cx) ->
99                // T is implemented for F, so we know the    lifetime going from
100                // 'de to T is sound. 3. In case of Ready, we won't touch
101                // raw_reader ever again here, and inner is left    empty.
102                // 4. In case of Pending, we know the inner is no longer borrowed (contract of
103                // the    poll_map_fn function), so we can get our Pin<&mut
104                // inner> back safely. 5. self.f must be called with Pin created
105                // from raw_inner to satisfy stacked    borrow rules.
106                let mut raw_inner = NonNull::from(inner.get_unchecked_mut());
107                match (self.f)(Pin::new_unchecked(raw_inner.as_mut()), cx) {
108                    Poll::Ready(v) => Poll::Ready(v),
109                    Poll::Pending => {
110                        self.inner = Some(Pin::new_unchecked(raw_inner.as_mut()));
111                        Poll::Pending
112                    },
113                }
114            }
115        }
116    }
117}