1//! Utility functions that are not specific to X11.
2//!
3//! # CSlice
4//!
5//! [`CSlice`] is a wrapper around some bytes in memory. It is unsafe to construct, but takes
6//! ownership of the bytes and allows accessing them as a `[u8]`. When dropped, the underlying
7//! memory is freed via [`libc::free`].
8//!
9//! `CSlice` is only available when the `allow-unsafe-code` feature is enabled.
10
11pub use x11rb_protocol::RawFdContainer;
12
13#[cfg(feature = "allow-unsafe-code")]
14mod unsafe_code {
15 use std::mem::forget;
16 use std::ops::{Deref, Index};
17 use std::ptr::NonNull;
18 use std::slice::{from_raw_parts, SliceIndex};
19
20 use libc::free;
21
22 /// Wrapper around a slice that was allocated in C code.
23 ///
24 /// `CSlice` is only available when the `allow-unsafe-code` feature is enabled.
25 pub struct CSlice {
26 ptr: NonNull<[u8]>,
27 }
28
29 // `CSlice` is `Send` and `Sync` because, once created, it is
30 // completely immutable (it does not have interior mutability),
31 // so it can be safely accessed from different threads simultaneously.
32 unsafe impl Send for CSlice {}
33 unsafe impl Sync for CSlice {}
34
35 impl CSlice {
36 /// Constructs a new `CSlice` from the given parts. `libc::free` will be called on the given
37 /// pointer when the slice is dropped.
38 ///
39 /// # Safety
40 ///
41 /// The same rules as for `std::slice::from_raw_parts` apply. Additionally, the given pointer
42 /// must be safe to free with `libc::free`.
43 pub unsafe fn new(ptr: *const u8, len: usize) -> CSlice {
44 CSlice {
45 ptr: NonNull::from(from_raw_parts(ptr, len)),
46 }
47 }
48
49 /// Convert `self` into a raw part.
50 ///
51 /// Ownership of the returned pointer is given to the caller. Specifically, `libc::free` will
52 /// not be called on it by `CSlice`.
53 pub fn into_ptr(self) -> *const u8 {
54 let ptr = self.ptr.as_ptr() as *const u8;
55 forget(self);
56 ptr
57 }
58 }
59
60 impl Drop for CSlice {
61 fn drop(&mut self) {
62 unsafe { free(self.ptr.as_ptr() as _) }
63 }
64 }
65
66 impl Deref for CSlice {
67 type Target = [u8];
68
69 fn deref(&self) -> &[u8] {
70 unsafe { self.ptr.as_ref() }
71 }
72 }
73
74 impl AsRef<[u8]> for CSlice {
75 fn as_ref(&self) -> &[u8] {
76 self
77 }
78 }
79
80 impl<I> Index<I> for CSlice
81 where
82 I: SliceIndex<[u8]>,
83 {
84 type Output = I::Output;
85
86 fn index(&self, index: I) -> &I::Output {
87 (**self).index(index)
88 }
89 }
90
91 impl std::fmt::Debug for CSlice {
92 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
93 std::fmt::Debug::fmt(&**self, f)
94 }
95 }
96}
97
98#[cfg(feature = "allow-unsafe-code")]
99pub use unsafe_code::CSlice;
100