1 | //! This crate provides the trait [`AsRawXcbConnection`]. |
2 | //! |
3 | //! The idea is to facilitate interoperability in the ecosystem. The problem is as follows: |
4 | //! |
5 | //! There are multiple crates that wrap the libxcb C API to provide a "connection" type. There are |
6 | //! also multiple crates wrapping various C libraries that need a pointer to `xcb_connection_t` |
7 | //! to work correctly. |
8 | //! |
9 | //! Without this library, API consumers must pick one Rust library that wraps libxcb and only |
10 | //! accept this type in its public API. Worse, one must also pick a specific version of the crate |
11 | //! and would then only work with that type. |
12 | //! |
13 | //! The trait [`AsRawXcbConnection`] breaks this connection. All libraries that wrap libxcb can |
14 | //! implement this trait. This makes one independent from specific versions of API consumer crates. |
15 | |
16 | #![allow (non_camel_case_types)] |
17 | #![no_std ] |
18 | |
19 | #[cfg (feature = "alloc" )] |
20 | extern crate alloc; |
21 | |
22 | use core::ptr::NonNull; |
23 | |
24 | /// XCB connection |
25 | /// |
26 | /// This type represents `xcb_connection_t` in C. It is only ever referenced via a pointer. |
27 | pub enum xcb_connection_t {} |
28 | |
29 | /// A trait to extract a raw `xcb_connection_t` from an object. |
30 | /// |
31 | /// # Safety |
32 | /// |
33 | /// This trait is unsafe. Implementations must provide a valid connection pointer that can be used |
34 | /// with libxcb C functions. This pointer must be valid for as long as the object on which this |
35 | /// trait is implemented. This means that the connection cannot be deallocated while the object is |
36 | /// still in use. |
37 | pub unsafe trait AsRawXcbConnection { |
38 | /// Get a raw xcb connection pointer from this object. |
39 | fn as_raw_xcb_connection(&self) -> *mut xcb_connection_t; |
40 | } |
41 | |
42 | // Implementations for reference types |
43 | |
44 | unsafe impl<T: AsRawXcbConnection + ?Sized> AsRawXcbConnection for &T { |
45 | fn as_raw_xcb_connection(&self) -> *mut xcb_connection_t { |
46 | (**self).as_raw_xcb_connection() |
47 | } |
48 | } |
49 | |
50 | unsafe impl<T: AsRawXcbConnection + ?Sized> AsRawXcbConnection for &mut T { |
51 | fn as_raw_xcb_connection(&self) -> *mut xcb_connection_t { |
52 | (**self).as_raw_xcb_connection() |
53 | } |
54 | } |
55 | |
56 | #[cfg (feature = "alloc" )] |
57 | unsafe impl<T: AsRawXcbConnection + ?Sized> AsRawXcbConnection for alloc::boxed::Box<T> { |
58 | fn as_raw_xcb_connection(&self) -> *mut xcb_connection_t { |
59 | (**self).as_raw_xcb_connection() |
60 | } |
61 | } |
62 | |
63 | #[cfg (feature = "alloc" )] |
64 | unsafe impl<T: AsRawXcbConnection + ?Sized> AsRawXcbConnection for alloc::rc::Rc<T> { |
65 | fn as_raw_xcb_connection(&self) -> *mut xcb_connection_t { |
66 | (**self).as_raw_xcb_connection() |
67 | } |
68 | } |
69 | |
70 | #[cfg (feature = "alloc" )] |
71 | unsafe impl<T: AsRawXcbConnection + ?Sized> AsRawXcbConnection for alloc::sync::Arc<T> { |
72 | fn as_raw_xcb_connection(&self) -> *mut xcb_connection_t { |
73 | (**self).as_raw_xcb_connection() |
74 | } |
75 | } |
76 | |
77 | #[cfg (feature = "alloc" )] |
78 | unsafe impl<T: AsRawXcbConnection + alloc::borrow::ToOwned + ?Sized> AsRawXcbConnection |
79 | for alloc::borrow::Cow<'_, T> |
80 | { |
81 | fn as_raw_xcb_connection(&self) -> *mut xcb_connection_t { |
82 | (**self).as_raw_xcb_connection() |
83 | } |
84 | } |
85 | |
86 | /// An assertion that this pointer is valid for as long as the underlying connection. |
87 | /// |
88 | /// This type provides an escape hatch for users who want to use a raw pointer to `xcb_connection_t` |
89 | /// but still want to use the safety guarantees of this crate. By constructing an instance of this |
90 | /// type, users can assert that the pointer is valid for as long as the underlying connection. |
91 | pub struct ValidConnection(NonNull<xcb_connection_t>); |
92 | |
93 | impl ValidConnection { |
94 | /// Create a new `ValidConnection` from a raw pointer. |
95 | /// |
96 | /// # Safety |
97 | /// |
98 | /// The pointer must be valid for as long as the underlying connection. |
99 | pub unsafe fn new(ptr: *mut xcb_connection_t) -> Self { |
100 | // SAFETY: Valid pointer implies non-null pointer. |
101 | Self(NonNull::new_unchecked(ptr)) |
102 | } |
103 | } |
104 | |
105 | unsafe impl AsRawXcbConnection for ValidConnection { |
106 | fn as_raw_xcb_connection(&self) -> *mut xcb_connection_t { |
107 | self.0.as_ptr() |
108 | } |
109 | } |
110 | |