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