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}