1 //! Topshim utils.
2 
3 use std::ffi::CString;
4 use std::marker::PhantomData;
5 use std::os::raw::c_char;
6 
7 /// Lifetime-checked const pointer wrapper.
8 ///
9 /// The wrapper holds the raw pointer and clones the lifetime from the pointing object,
10 /// which forces the compiler to check and fail when the wrapper lives longer than the data.
11 ///
12 /// Example 1:
13 ///     Get the pointer with from_ref(), and pass the pointer into() a C function.
14 ///     ```
15 ///     // let addr: RawAddress;
16 ///     let addr_ptr = LTCheckedPtr::from_ref(&addr);
17 ///     // The pointer type would be `*const RawAddress`.
18 ///     ccall!(self, foo, addr_ptr.into());
19 ///     ```
20 ///
21 /// Example 2:
22 ///     Get the pointer from() an array-like type, such as slice, Vec, and String.
23 ///     Cast and pass the pointer into a C function with cast_into().
24 ///     ```
25 ///     // let profile: Vec<u8>;
26 ///     let profile_ptr = LTCheckedPtr::from(&profile);
27 ///     // The pointer type would be `*const c_char`.
28 ///     ccall!(self, bar, profile_ptr.cast_into::<c_char>());
29 ///     ```
30 ///
31 /// Example 3:
32 ///     Get the pointer from() a Box or Option, and pass the pointer into() a C function.
33 ///     ```
34 ///     // let uuid: Option<Uuid>;
35 ///     let uuid_ptr = LTCheckedPtr::from(&uuid);
36 ///     // The pointer type would be `*const Uuid`, while it could be NULL.
37 ///     ccall!(self, foobar, uuid_ptr.into());
38 ///     ```
39 pub(crate) struct LTCheckedPtr<'a, T> {
40     ptr: *const T,
41     _covariant: PhantomData<&'a ()>,
42 }
43 
44 impl<T> LTCheckedPtr<'static, T> {
45     /// Returns a null pointer, which has static lifetime.
null() -> Self46     pub(crate) fn null() -> Self {
47         Self { ptr: std::ptr::null(), _covariant: PhantomData }
48     }
49 }
50 
51 impl<'a, T> LTCheckedPtr<'a, T> {
52     /// Constructs a lifetime-checked constant pointer from a reference.
from_ref(val: &'a T) -> Self53     pub(crate) fn from_ref(val: &'a T) -> Self {
54         Self { ptr: val, _covariant: PhantomData }
55     }
56 
57     /// Returns the casted raw constant pointer.
cast_into<CT>(self) -> *const CT58     pub(crate) fn cast_into<CT>(self) -> *const CT {
59         self.ptr as *const CT
60     }
61 }
62 
63 impl<'a, T> Into<*const T> for LTCheckedPtr<'a, T> {
into(self) -> *const T64     fn into(self) -> *const T {
65         self.ptr
66     }
67 }
68 
69 impl<'a, T> From<&'a [T]> for LTCheckedPtr<'a, T> {
from(val: &'a [T]) -> Self70     fn from(val: &'a [T]) -> Self {
71         Self { ptr: val.as_ptr(), _covariant: PhantomData }
72     }
73 }
74 
75 impl<'a, T> From<&'a Vec<T>> for LTCheckedPtr<'a, T> {
from(val: &'a Vec<T>) -> Self76     fn from(val: &'a Vec<T>) -> Self {
77         Self { ptr: val.as_ptr(), _covariant: PhantomData }
78     }
79 }
80 
81 impl<'a> From<&'a String> for LTCheckedPtr<'a, u8> {
from(val: &'a String) -> Self82     fn from(val: &'a String) -> Self {
83         Self { ptr: val.as_ptr(), _covariant: PhantomData }
84     }
85 }
86 
87 impl<'a> From<&'a CString> for LTCheckedPtr<'a, c_char> {
from(val: &'a CString) -> Self88     fn from(val: &'a CString) -> Self {
89         Self { ptr: val.as_ptr(), _covariant: PhantomData }
90     }
91 }
92 
93 impl<'a, T> From<&'a Option<T>> for LTCheckedPtr<'a, T> {
from(val: &'a Option<T>) -> Self94     fn from(val: &'a Option<T>) -> Self {
95         match val {
96             Some(ref v) => Self { ptr: v, _covariant: PhantomData },
97             None => LTCheckedPtr::null(),
98         }
99     }
100 }
101 
102 impl<'a, T> From<&'a Box<T>> for LTCheckedPtr<'a, T> {
from(val: &'a Box<T>) -> Self103     fn from(val: &'a Box<T>) -> Self {
104         Self { ptr: &**val, _covariant: PhantomData }
105     }
106 }
107 
108 /// Lifetime-checked mutable pointer wrapper.
109 ///
110 /// The wrapper holds the raw pointer and clones the lifetime from the pointing object,
111 /// which forces the compiler to check and fail when the wrapper lives longer than the data.
112 ///
113 /// Example 1:
114 ///     Get the pointer with from_ref(), and pass the pointer into() a C function.
115 ///     ```
116 ///     // let mut record: bluetooth_sdp_record;
117 ///     let record_ptr = LTCheckedPtrMut::from_ref(&mut report);
118 ///     // The pointer type would be `*mut bluetooth_sdp_record`.
119 ///     ccall!(self, foo, record_ptr.into());
120 ///     ```
121 ///
122 /// Example 2:
123 ///     Get the pointer from() an array-like type, such as slice, Vec, and String.
124 ///     Cast and pass the pointer into a C function with cast_into().
125 ///     ```
126 ///     // let mut report: [u8];
127 ///     let report_ptr = LTCheckedPtrMut::from(&mut report);
128 ///     // The pointer type would be `*mut c_char`.
129 ///     ccall!(self, bar, report_ptr.cast_into::<c_char>());
130 ///     ```
131 ///
132 /// Example 3:
133 ///     Get the pointer from() a Box or Option, and pass the pointer into() a C function.
134 ///     ```
135 ///     // let mut callbacks: Box<bt_callbacks_t>;
136 ///     let cb_ptr = LTCheckedPtrMut::from(&mut callbacks);
137 ///     // The pointer type would be `*mut bt_callbacks_t`.
138 ///     ccall!(self, init, cb_ptr.into());
139 ///     ```
140 pub(crate) struct LTCheckedPtrMut<'a, T> {
141     ptr: *mut T,
142     _covariant: PhantomData<&'a ()>,
143 }
144 
145 impl<T> LTCheckedPtrMut<'static, T> {
146     /// Returns a null pointer, which has static lifetime.
null() -> Self147     pub(crate) fn null() -> Self {
148         Self { ptr: std::ptr::null_mut(), _covariant: PhantomData }
149     }
150 }
151 
152 impl<'a, T> LTCheckedPtrMut<'a, T> {
153     /// Constructs a lifetime-checked mutable pointer from a reference.
from_ref(val: &'a mut T) -> Self154     pub(crate) fn from_ref(val: &'a mut T) -> Self {
155         Self { ptr: val, _covariant: PhantomData }
156     }
157 
158     /// Returns the casted raw mutable pointer.
cast_into<CT>(self) -> *mut CT159     pub(crate) fn cast_into<CT>(self) -> *mut CT {
160         self.ptr as *mut CT
161     }
162 }
163 
164 impl<'a, T> Into<*mut T> for LTCheckedPtrMut<'a, T> {
into(self) -> *mut T165     fn into(self) -> *mut T {
166         self.ptr
167     }
168 }
169 
170 impl<'a, T> From<&'a mut [T]> for LTCheckedPtrMut<'a, T> {
from(val: &'a mut [T]) -> Self171     fn from(val: &'a mut [T]) -> Self {
172         Self { ptr: val.as_mut_ptr(), _covariant: PhantomData }
173     }
174 }
175 
176 impl<'a, T> From<&'a mut Vec<T>> for LTCheckedPtrMut<'a, T> {
from(val: &'a mut Vec<T>) -> Self177     fn from(val: &'a mut Vec<T>) -> Self {
178         Self { ptr: val.as_mut_ptr(), _covariant: PhantomData }
179     }
180 }
181 
182 impl<'a> From<&'a mut String> for LTCheckedPtrMut<'a, u8> {
from(val: &'a mut String) -> Self183     fn from(val: &'a mut String) -> Self {
184         Self { ptr: val.as_mut_ptr(), _covariant: PhantomData }
185     }
186 }
187 
188 impl<'a, T> From<&'a mut Option<T>> for LTCheckedPtrMut<'a, T> {
from(val: &'a mut Option<T>) -> Self189     fn from(val: &'a mut Option<T>) -> Self {
190         match val {
191             Some(ref mut v) => Self { ptr: v, _covariant: PhantomData },
192             None => LTCheckedPtrMut::null(),
193         }
194     }
195 }
196 
197 impl<'a, T> From<&'a mut Box<T>> for LTCheckedPtrMut<'a, T> {
from(val: &'a mut Box<T>) -> Self198     fn from(val: &'a mut Box<T>) -> Self {
199         Self { ptr: &mut **val, _covariant: PhantomData }
200     }
201 }
202