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")]
20extern crate alloc;
21
22use 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.
27pub 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.
37pub 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
44unsafe 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
50unsafe 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")]
57unsafe 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")]
64unsafe 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")]
71unsafe 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")]
78unsafe 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.
91pub struct ValidConnection(NonNull<xcb_connection_t>);
92
93impl 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
105unsafe impl AsRawXcbConnection for ValidConnection {
106 fn as_raw_xcb_connection(&self) -> *mut xcb_connection_t {
107 self.0.as_ptr()
108 }
109}
110