x11rb_async/
connection.rs

1// This code is dual licensed under MIT OR Apache 2.0.
2
3//! Generic connection-related traits.
4
5use x11rb::connection::{BufWithFds, EventAndSeqNumber, ReplyOrError, RequestKind};
6use x11rb::utils::RawFdContainer as OwnedFd;
7use x11rb_protocol::protocol::xproto::Setup;
8use x11rb_protocol::protocol::Event;
9use x11rb_protocol::x11_utils::{
10    ExtensionInformation, ReplyFDsRequest, ReplyRequest, TryParse, TryParseFd, VoidRequest,
11    X11Error,
12};
13use x11rb_protocol::{DiscardMode, RawEventAndSeqNumber, SequenceNumber};
14
15use crate::errors::{ConnectionError, ParseError, ReplyError, ReplyOrIdError};
16use crate::{Cookie, CookieWithFds, VoidCookie};
17
18use std::future::Future;
19use std::io::IoSlice;
20use std::pin::Pin;
21
22pub(crate) type Fut<'a, T, E> = Pin<Box<dyn Future<Output = Result<T, E>> + Send + 'a>>;
23
24/// A connection to an X11 server for sending requests.
25pub trait RequestConnection: Sync {
26    /// Type used as buffer to store raw replies or events before
27    /// they are parsed.
28    type Buf: AsRef<[u8]> + std::fmt::Debug + Send + Sync + 'static;
29
30    /// Send a request with a reply to the server.
31    ///
32    /// This is the `async` analog of [`x11rb::connection::RequestConnection::send_request_with_reply`], and is
33    /// semantically equivalent to:
34    ///
35    /// ```no_compile
36    /// async fn send_request_with_reply<R: TryParse>(
37    ///     &self,
38    ///     bufs: &[IoSlice],
39    ///     fds: Vec<RawFdContainer>
40    /// ) -> Result<Cookie<'_, Self, R>, ConnectionError>
41    /// ```
42    fn send_request_with_reply<'this, 'bufs, 'sl, 're, 'future, R>(
43        &'this self,
44        bufs: &'bufs [IoSlice<'sl>],
45        fds: Vec<OwnedFd>,
46    ) -> Fut<'future, Cookie<'this, Self, R>, ConnectionError>
47    where
48        'this: 'future,
49        'bufs: 'future,
50        'sl: 'future,
51        're: 'future,
52        R: TryParse + Send + 're;
53
54    /// Send a request with a reply to the server.
55    ///
56    /// Rather than sending raw bytes, this method sends the trait object.
57    ///
58    /// This is the `async` analog of [`x11rb::connection::RequestConnection::send_trait_request_with_reply`], and
59    /// is semantically equivalent to:
60    ///
61    /// ```no_compile
62    /// async fn send_trait_request_with_reply<R: ReplyRequest>(
63    ///     &self,
64    ///     request: R
65    /// ) -> Result<Cookie<'_, Self, R::Reply>, ConnectionError>
66    /// ```
67    fn send_trait_request_with_reply<'this, 'req, 'future, R>(
68        &'this self,
69        request: R,
70    ) -> Fut<'future, Cookie<'_, Self, R::Reply>, ConnectionError>
71    where
72        'this: 'future,
73        'req: 'future,
74        R: ReplyRequest + Send + 'req,
75        R::Reply: Send,
76    {
77        Box::pin(async move {
78            let opcode = match R::EXTENSION_NAME {
79                None => 0,
80                Some(extension) => {
81                    self.extension_information(extension)
82                        .await?
83                        .ok_or(ConnectionError::UnsupportedExtension)?
84                        .major_opcode
85                }
86            };
87
88            let (buf, fds) = request.serialize(opcode);
89            self.send_request_with_reply(&[IoSlice::new(&buf)], fds)
90                .await
91        })
92    }
93
94    /// Send a request with a reply containing file descriptors to the server.
95    ///
96    /// This is the `async` analog of [`x11rb::connection::RequestConnection::send_request_with_reply_with_fds`], and
97    /// is semantically equivalent to:
98    ///
99    /// ```no_compile
100    /// async fn send_request_with_reply_with_fds<R: TryParseFd>(
101    ///     &self,
102    ///     bufs: &[IoSlice],
103    ///     fds: Vec<RawFdContainer>,
104    /// ) -> Result<CookieWithFds<'_, Self, R>, ConnectionError>
105    /// ```
106    fn send_request_with_reply_with_fds<'this, 'bufs, 'sl, 're, 'future, R>(
107        &'this self,
108        bufs: &'bufs [IoSlice<'sl>],
109        fds: Vec<OwnedFd>,
110    ) -> Fut<'future, CookieWithFds<'this, Self, R>, ConnectionError>
111    where
112        'this: 'future,
113        'bufs: 'future,
114        'sl: 'future,
115        're: 'future,
116        R: TryParseFd + Send + 're;
117
118    /// Send a request with a reply containing file descriptors to the server.
119    ///
120    /// Rather than sending raw bytes, this method sends the trait object.
121    ///
122    /// This is the `async` analog of [`x11rb::connection::RequestConnection::send_trait_request_with_reply_with_fds`],
123    /// and is semantically equivalent to:
124    ///
125    /// ```no_compile
126    /// async fn send_trait_request_with_reply_with_fds<R: ReplyFDsRequest>(
127    ///     &self,
128    ///     request: R
129    /// ) -> Result<CookieWithFds<'_, Self, R::Reply>, ConnectionError>
130    /// ```
131    fn send_trait_request_with_reply_with_fds<'this, 'req, 'future, R>(
132        &'this self,
133        request: R,
134    ) -> Fut<'future, CookieWithFds<'_, Self, R::Reply>, ConnectionError>
135    where
136        'this: 'future,
137        'req: 'future,
138        R: ReplyFDsRequest + Send + 'req,
139        R::Reply: Send,
140    {
141        Box::pin(async move {
142            let opcode = match R::EXTENSION_NAME {
143                None => 0,
144                Some(extension) => {
145                    self.extension_information(extension)
146                        .await?
147                        .ok_or(ConnectionError::UnsupportedExtension)?
148                        .major_opcode
149                }
150            };
151
152            let (buf, fds) = request.serialize(opcode);
153            self.send_request_with_reply_with_fds(&[IoSlice::new(&buf)], fds)
154                .await
155        })
156    }
157
158    /// Send a request without a reply to the server.
159    ///
160    /// This is the `async` analog of [`x11rb::connection::RequestConnection::send_request_without_reply`], and is
161    /// semantically equivalent to:
162    ///
163    /// ```no_compile
164    /// async fn send_request_without_reply(
165    ///     &self,
166    ///     bufs: &[IoSlice],
167    ///     fds: Vec<RawFdContainer>,
168    /// ) -> Result<VoidCookie<'_, Self>, ConnectionError>
169    /// ```
170    fn send_request_without_reply<'this, 'bufs, 'sl, 'future>(
171        &'this self,
172        bufs: &'bufs [IoSlice<'sl>],
173        fds: Vec<OwnedFd>,
174    ) -> Fut<'future, VoidCookie<'this, Self>, ConnectionError>
175    where
176        'this: 'future,
177        'bufs: 'future,
178        'sl: 'future;
179
180    /// Send a request without a reply to the server.
181    ///
182    /// Rather than sending raw bytes, this method sends the trait object.
183    ///
184    /// This is the `async` analog of [`x11rb::connection::RequestConnection::send_trait_request_without_reply`],
185    /// and is semantically equivalent to:
186    ///
187    /// ```no_compile
188    /// async fn send_trait_request_without_reply<R: VoidRequest>(
189    ///     &self,
190    ///     request: R
191    /// ) -> Result<VoidCookie<'_, Self>, ConnectionError>
192    /// ```
193    fn send_trait_request_without_reply<'this, 'req, 'future, R>(
194        &'this self,
195        request: R,
196    ) -> Fut<'future, VoidCookie<'this, Self>, ConnectionError>
197    where
198        'this: 'future,
199        'req: 'future,
200        R: VoidRequest + Send + 'req,
201    {
202        Box::pin(async move {
203            let opcode = match R::EXTENSION_NAME {
204                None => 0,
205                Some(extension) => {
206                    self.extension_information(extension)
207                        .await?
208                        .ok_or(ConnectionError::UnsupportedExtension)?
209                        .major_opcode
210                }
211            };
212
213            let (buf, fds) = request.serialize(opcode);
214            self.send_request_without_reply(&[IoSlice::new(&buf)], fds)
215                .await
216        })
217    }
218
219    /// The reply for this request shoiuld be discarded.
220    fn discard_reply(&self, sequence: SequenceNumber, kind: RequestKind, mode: DiscardMode);
221
222    /// Prefetch information about an extension.
223    ///
224    /// This is the `async` analog of [`x11rb::connection::RequestConnection::prefetch_extension_information`], and
225    /// is semantically equivalent to:
226    ///
227    /// ```no_compile
228    /// async fn prefetch_extension_information(&self, name: &'static str) -> Result<(), ConnectionError>
229    /// ```
230    fn prefetch_extension_information(&self, name: &'static str) -> Fut<'_, (), ConnectionError>;
231
232    /// Get information about an extension.
233    ///
234    /// This is the `async` analog of [`x11rb::connection::RequestConnection::extension_information`], and is
235    /// semantically equivalent to:
236    ///
237    /// ```no_compile
238    /// async fn extension_information(&self, name: &'static str)
239    ///     -> Result<Option<ExtensionInformation>, ConnectionError>
240    /// ```
241    fn extension_information(
242        &self,
243        name: &'static str,
244    ) -> Fut<'_, Option<ExtensionInformation>, ConnectionError>;
245
246    /// Wait for the reply to a request.
247    ///
248    /// This is the `async` analog of [`x11rb::connection::RequestConnection::wait_for_reply_or_error`], and is
249    /// semantically equivalent to:
250    ///
251    /// ```no_compile
252    /// async fn wait_for_reply_or_error(
253    ///     &self,
254    ///     sequence: SequenceNumber,
255    /// ) -> Result<ReplyOrError<Self::Buf>, ConnectionError>
256    /// ```
257    fn wait_for_reply_or_error(&self, sequence: SequenceNumber) -> Fut<'_, Self::Buf, ReplyError> {
258        Box::pin(async move {
259            let reply_or_error = self.wait_for_reply_or_raw_error(sequence).await?;
260            match reply_or_error {
261                ReplyOrError::Reply(reply) => Ok(reply),
262                ReplyOrError::Error(error) => Err(self.parse_error(error.as_ref())?.into()),
263            }
264        })
265    }
266
267    /// Wait for the reply to a request.
268    ///
269    /// This is the `async` analog of [`x11rb::connection::RequestConnection::wait_for_reply_or_raw_error`], and is
270    /// semantically equivalent to:
271    ///
272    /// ```no_compile
273    /// async fn wait_for_reply_or_raw_error(
274    ///     &self,
275    ///     sequence: SequenceNumber,
276    /// ) -> Result<ReplyOrError<Self::Buf>, ConnectionError>
277    /// ```
278    fn wait_for_reply_or_raw_error(
279        &self,
280        sequence: SequenceNumber,
281    ) -> Fut<'_, ReplyOrError<Self::Buf>, ConnectionError>;
282
283    /// Wait for the reply to a request.
284    ///
285    /// This is the `async` analog of [`x11rb::connection::RequestConnection::wait_for_reply`], and is semantically
286    /// equivalent to:
287    ///
288    /// ```no_compile
289    /// async fn wait_for_reply(
290    ///     &self,
291    ///     sequence: SequenceNumber,
292    /// ) -> Result<Option<Self::Buf>, ConnectionError>
293    /// ```
294    fn wait_for_reply(
295        &self,
296        sequence: SequenceNumber,
297    ) -> Fut<'_, Option<Self::Buf>, ConnectionError>;
298
299    /// Wait for the reply to a request with file descriptors.
300    ///
301    /// This is the `async` analog of [`x11rb::connection::RequestConnection::wait_for_reply_with_fds`], and is
302    /// semantically equivalent to:
303    ///
304    /// ```no_compile
305    /// async fn wait_for_reply_with_fds(
306    ///     &self,
307    ///     sequence: SequenceNumber,
308    /// ) -> Result<BufWithFds<Self::Buf>, ConnectionError>
309    /// ```
310    fn wait_for_reply_with_fds(
311        &self,
312        sequence: SequenceNumber,
313    ) -> Fut<'_, BufWithFds<Self::Buf>, ReplyError> {
314        Box::pin(async move {
315            let reply_or_error = self.wait_for_reply_with_fds_raw(sequence).await?;
316            match reply_or_error {
317                ReplyOrError::Reply(reply) => Ok(reply),
318                ReplyOrError::Error(error) => Err(self.parse_error(error.as_ref())?.into()),
319            }
320        })
321    }
322
323    /// Wait for the reply to a request with file descriptors.
324    ///
325    /// This is the `async` analog of [`x11rb::connection::RequestConnection::wait_for_reply_with_fds_raw`], and is
326    /// semantically equivalent to:
327    ///
328    /// ```no_compile
329    /// async fn wait_for_reply_with_fds_raw(
330    ///     &self,
331    ///     sequence: SequenceNumber,
332    /// ) -> Result<ReplyOrError<BufWithFds<Self::Buf>, Self::Buf>, ConnectionError>
333    /// ```
334    fn wait_for_reply_with_fds_raw(
335        &self,
336        sequence: SequenceNumber,
337    ) -> Fut<'_, ReplyOrError<BufWithFds<Self::Buf>, Self::Buf>, ConnectionError>;
338
339    /// Check whether a request has errored.
340    ///
341    /// This is the `async` analog of [`x11rb::connection::RequestConnection::check_for_error`], and is semantically
342    /// equivalent to:
343    ///
344    /// ```no_compile
345    /// async fn check_for_error(
346    ///     &self,
347    ///     sequence: SequenceNumber,
348    /// ) -> Result<(), ReplyError>
349    /// ```
350    fn check_for_error(&self, sequence: SequenceNumber) -> Fut<'_, (), ReplyError> {
351        Box::pin(async move {
352            let error = self.check_for_raw_error(sequence).await?;
353            if let Some(error) = error {
354                Err(self.parse_error(error.as_ref())?.into())
355            } else {
356                Ok(())
357            }
358        })
359    }
360
361    /// Check whether a request has errored.
362    ///
363    /// This is the `async` analog of [`x11rb::connection::RequestConnection::check_for_raw_error`], and is
364    /// semantically equivalent to:
365    ///
366    /// ```no_compile
367    /// async fn check_for_raw_error(
368    ///     &self,
369    ///     sequence: SequenceNumber,
370    /// ) -> Result<Option<Self::Buf>, ConnectionError>
371    /// ```
372    fn check_for_raw_error(
373        &self,
374        sequence: SequenceNumber,
375    ) -> Fut<'_, Option<Self::Buf>, ConnectionError>;
376
377    /// Prefetches the maximum request length.
378    ///
379    /// This is the `async` analog of [`x11rb::connection::RequestConnection::prefetch_maximum_request_bytes`], and
380    /// is semantically equivalent to:
381    ///
382    /// ```no_compile
383    /// async fn prefetch_maximum_request_bytes(&self)
384    /// ```
385    fn prefetch_maximum_request_bytes(&self) -> Pin<Box<dyn Future<Output = ()> + Send + '_>>;
386
387    /// Get the maximum request length.
388    ///
389    /// This is the `async` analog of [`x11rb::connection::RequestConnection::maximum_request_bytes`], and is
390    /// semantically equivalent to:
391    ///
392    /// ```no_compile
393    /// async fn maximum_request_bytes(&self) -> usize
394    /// ```
395    fn maximum_request_bytes(&self) -> Pin<Box<dyn Future<Output = usize> + Send + '_>>;
396
397    /// Parse a generic error.
398    fn parse_error(&self, error: &[u8]) -> Result<X11Error, ParseError>;
399
400    /// Parse a generic event.
401    fn parse_event(&self, event: &[u8]) -> Result<Event, ParseError>;
402}
403
404/// An asynchronous connection to an X11 server.
405pub trait Connection: RequestConnection {
406    /// Wait for a new event from the X11 server.
407    ///
408    /// This is the `async` analog of [`x11rb::connection::Connection::wait_for_event`], and is semantically equivalent
409    /// to:
410    ///
411    /// ```no_compile
412    /// async fn wait_for_event(&self) -> Result<Event, ConnectionError>
413    /// ```
414    fn wait_for_event(&self) -> Fut<'_, Event, ConnectionError> {
415        Box::pin(async move { Ok(self.wait_for_event_with_sequence().await?.0) })
416    }
417
418    /// Wait for a new event from the X11 server.
419    ///
420    /// This is the `async` analog of [`x11rb::connection::Connection::wait_for_raw_event`], and is semantically
421    /// equivalent to:
422    ///
423    /// ```no_compile
424    /// async fn wait_for_raw_event(&self) -> Result<Self::Buf, ConnectionError>
425    /// ```
426    fn wait_for_raw_event(&self) -> Fut<'_, Self::Buf, ConnectionError> {
427        Box::pin(async move { Ok(self.wait_for_raw_event_with_sequence().await?.0) })
428    }
429
430    /// Wait for a new event from the X11 server.
431    ///
432    /// This is the `async` analog of [`x11rb::connection::Connection::wait_for_event_with_sequence`], and is semantically
433    /// equivalent to:
434    ///
435    /// ```no_compile
436    /// async fn wait_for_event_with_sequence(
437    ///     &self,
438    ///     sequence: SequenceNumber,
439    /// ) -> Result<EventAndSeqNumber, ConnectionError>
440    /// ```
441    fn wait_for_event_with_sequence(&self) -> Fut<'_, EventAndSeqNumber, ConnectionError> {
442        Box::pin(async move {
443            let (event, seq) = self.wait_for_raw_event_with_sequence().await?;
444            let event = self.parse_event(event.as_ref())?;
445            Ok((event, seq))
446        })
447    }
448
449    /// Wait for a raw/unparsed event from the X11 server.
450    ///
451    /// This is the `async` analog of [`x11rb::connection::Connection::wait_for_raw_event`], and is semantically
452    /// equivalent to:
453    ///
454    /// ```no_compile
455    /// async fn wait_for_raw_event(&self) -> Result<RawEvent<Self::Buf>, ConnectionError>
456    /// ```
457    fn wait_for_raw_event_with_sequence(
458        &self,
459    ) -> Fut<'_, RawEventAndSeqNumber<Self::Buf>, ConnectionError>;
460
461    /// Poll for a new event from the X11 server.
462    fn poll_for_event(&self) -> Result<Option<Event>, ConnectionError> {
463        Ok(self.poll_for_event_with_sequence()?.map(|(event, _)| event))
464    }
465
466    /// Poll for a raw/unparsed event from the X11 server.
467    fn poll_for_raw_event(&self) -> Result<Option<Self::Buf>, ConnectionError> {
468        Ok(self
469            .poll_for_raw_event_with_sequence()?
470            .map(|(event, _)| event))
471    }
472
473    /// Poll for a new event from the X11 server.
474    fn poll_for_event_with_sequence(&self) -> Result<Option<EventAndSeqNumber>, ConnectionError> {
475        let raw = self.poll_for_raw_event_with_sequence()?;
476
477        match raw {
478            Some((raw, seq)) => {
479                let event = self.parse_event(raw.as_ref())?;
480                Ok(Some((event, seq)))
481            }
482            None => Ok(None),
483        }
484    }
485
486    /// Poll for a raw/unparsed event from the X11 server.
487    fn poll_for_raw_event_with_sequence(
488        &self,
489    ) -> Result<Option<RawEventAndSeqNumber<Self::Buf>>, ConnectionError>;
490
491    /// Flush the output buffer.
492    fn flush(&self) -> Fut<'_, (), ConnectionError>;
493
494    /// Get the setup information of the connection.
495    fn setup(&self) -> &Setup;
496
497    /// Generate a new X11 identifier.
498    ///
499    /// This is the `async` analog of [`x11rb::connection::Connection::generate_id`], and is the semantic equivalent
500    /// to:
501    ///
502    /// ```no_compile
503    /// async fn generate_id(&self) -> Result<u32, ReplyOrIdError>
504    /// ```
505    fn generate_id(&self) -> Fut<'_, u32, ReplyOrIdError>;
506}