1 /*
2 * Copyright (C) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 use crate::{IpcResult, IpcStatusCode, status_result, BorrowedMsgParcel, ipc_binding, AsRawPtr};
17 use std::mem::MaybeUninit;
18 use std::ffi::{c_void, c_ulong};
19 use std::ptr;
20
21 /// Implement `Serialize` trait to serialize a custom MsgParcel.
22 ///
23 /// # Example:
24 ///
25 /// ```ignore
26 /// struct Year(i64);
27 ///
28 /// impl Serialize for Year {
29 /// fn serialize(&self, parcel: &mut BorrowedMsgParcel<'_>) -> IpcResult<()> {
30 /// parcel::write(self.0);
31 /// }
32 /// }
33 /// ```
34 pub trait Serialize {
35 /// Serialize Self to BorrowedMsgParcel
serialize(&self, parcel: &mut BorrowedMsgParcel<'_>) -> IpcResult<()>36 fn serialize(&self, parcel: &mut BorrowedMsgParcel<'_>) -> IpcResult<()>;
37 }
38
39 /// Implement `Deserialize` trait to deserialize a custom MsgParcel.
40 ///
41 /// # Example:
42 ///
43 /// ```ignore
44 /// struct Year(i64);
45 ///
46 /// impl Deserialize for Year {
47 /// fn deserialize(parcel: &mut BorrowedMsgParcel<'_>) -> IpcResult<Self> {
48 /// let i = parcel::read::<i64>(parcel);
49 /// Ok(Year(i))
50 /// }
51 /// }
52 /// ```
53 pub trait Deserialize: Sized {
54 /// Deserialize an instance from the given [`Parcel`].
deserialize(parcel: &BorrowedMsgParcel<'_>) -> IpcResult<Self>55 fn deserialize(parcel: &BorrowedMsgParcel<'_>) -> IpcResult<Self>;
56 }
57
58 pub const NULL_FLAG : i32 = 0;
59 pub const NON_NULL_FLAG : i32 = 1;
60
61 /// Define trait function for Option<T> which T must implements the trait Serialize.
62 pub trait SerOption: Serialize {
63 /// Serialize the Option<T>
ser_option(this: Option<&Self>, parcel: &mut BorrowedMsgParcel<'_>) -> IpcResult<(), >64 fn ser_option(this: Option<&Self>, parcel: &mut BorrowedMsgParcel<'_>) -> IpcResult<(), > {
65 if let Some(inner) = this {
66 parcel.write(&NON_NULL_FLAG)?;
67 parcel.write(inner)
68 } else {
69 parcel.write(&NULL_FLAG)
70 }
71 }
72 }
73
74 /// Define trait function for Option<T> which T must implements the trait Deserialize.
75 pub trait DeOption: Deserialize {
76 /// Deserialize the Option<T>
de_option(parcel: &BorrowedMsgParcel<'_>) -> IpcResult<Option<Self>>77 fn de_option(parcel: &BorrowedMsgParcel<'_>) -> IpcResult<Option<Self>> {
78 let null: i32 = parcel.read()?;
79 if null == NULL_FLAG {
80 Ok(None)
81 } else {
82 parcel.read().map(Some)
83 }
84 }
85 }
86
87 /// Callback to allocate a vector for parcel array read functions.
88 ///
89 /// # Safety
90 ///
91 /// The opaque data pointer passed to the array read function must be a mutable
92 /// pointer to an `Option<Vec<MaybeUninit<T>>>`.
allocate_vec_with_buffer<T>( value: *mut c_void, buffer: *mut *mut T, len: i32 ) -> bool93 pub unsafe extern "C" fn allocate_vec_with_buffer<T>(
94 value: *mut c_void,
95 buffer: *mut *mut T,
96 len: i32
97 ) -> bool {
98 let res = allocate_vec::<T>(value, len);
99 // `buffer` will be assigned a mutable pointer to the allocated vector data
100 // if this function returns true.
101 let vec = &mut *(value as *mut Option<Vec<MaybeUninit<T>>>);
102 if let Some(new_vec) = vec {
103 *buffer = new_vec.as_mut_ptr() as *mut T;
104 }
105 res
106 }
107
108 /// Callback to allocate a vector for parcel array read functions.
109 ///
110 /// # Safety
111 ///
112 /// The opaque data pointer passed to the array read function must be a mutable
113 /// pointer to an `Option<Vec<MaybeUninit<T>>>`.
allocate_vec<T>( value: *mut c_void, len: i32, ) -> bool114 unsafe extern "C" fn allocate_vec<T>(
115 value: *mut c_void,
116 len: i32,
117 ) -> bool {
118 if len < 0 {
119 return true;
120 }
121 allocate_vec_maybeuninit::<T>(value, len as u32);
122 true
123 }
124
125 /// Helper trait for types that can be serialized as arrays.
126 /// Defaults to calling Serialize::serialize() manually for every element,
127 /// but can be overridden for custom implementations like `writeByteArray`.
128 // Until specialization is stabilized in Rust, we need this to be a separate
129 // trait because it's the only way to have a default implementation for a method.
130 // We want the default implementation for most types, but an override for
131 // a few special ones like `readByteArray` for `u8`.
132 pub trait SerArray: Serialize + Sized {
133 /// Default array serialize implement.
ser_array(slice: &[Self], parcel: &mut BorrowedMsgParcel<'_>) -> IpcResult<()>134 fn ser_array(slice: &[Self], parcel: &mut BorrowedMsgParcel<'_>) -> IpcResult<()> {
135 // SAFETY: Safe FFI, slice will always be a safe pointer to pass.
136 let ret = unsafe {
137 ipc_binding::CParcelWriteParcelableArray(
138 parcel.as_mut_raw(),
139 slice.as_ptr() as *const c_void,
140 slice.len().try_into().unwrap(),
141 ser_element::<Self>,
142 )
143 };
144 status_result::<()>(ret as i32, ())
145 }
146 }
147
148 /// Callback to serialize an element of a generic parcelable array.
149 ///
150 /// # Safety
151 ///
152 /// We are relying on c interface to not overrun our slice. As long
153 /// as it doesn't provide an index larger than the length of the original
154 /// slice in serialize_array, this operation is safe. The index provided
155 /// is zero-based.
156 #[allow(dead_code)]
ser_element<T: Serialize>( parcel: *mut ipc_binding::CParcel, array: *const c_void, index: c_ulong, ) -> bool157 pub(crate) unsafe extern "C" fn ser_element<T: Serialize>(
158 parcel: *mut ipc_binding::CParcel,
159 array: *const c_void,
160 index: c_ulong,
161 ) -> bool {
162 // c_ulong and usize are the same, but we need the explicitly sized version
163 // so the function signature matches what bindgen generates.
164 let index = index as usize;
165
166 let slice: &[T] = std::slice::from_raw_parts(array.cast(), index+1);
167
168 let mut parcel = match BorrowedMsgParcel::from_raw(parcel) {
169 None => return false,
170 Some(p) => p,
171 };
172 slice[index].serialize(&mut parcel).is_ok()
173 }
174
175 /// Helper trait for types that can be deserialized as arrays.
176 /// Defaults to calling Deserialize::deserialize() manually for every element,
177 /// but can be overridden for custom implementations like `readByteArray`.
178 pub trait DeArray: Deserialize {
179 /// Deserialize an array of type from the given parcel.
de_array(parcel: &BorrowedMsgParcel<'_>) -> IpcResult<Option<Vec<Self>>>180 fn de_array(parcel: &BorrowedMsgParcel<'_>) -> IpcResult<Option<Vec<Self>>> {
181 let mut vec: Option<Vec<MaybeUninit<Self>>> = None;
182 // SAFETY:
183 // Safe FFI, vec is the correct opaque type expected by
184 // allocate_vec and de_element.
185 let ok_status = unsafe {
186 ipc_binding::CParcelReadParcelableArray(
187 parcel.as_raw(),
188 &mut vec as *mut _ as *mut c_void,
189 allocate_vec::<Self>,
190 de_element::<Self>,
191 )
192 };
193
194 if ok_status{
195 // SAFETY:
196 // We are assuming that the C-API correctly initialized every
197 // element of the vector by now, so we know that all the
198 // MaybeUninits are now properly initialized. We can transmute from
199 // Vec<MaybeUninit<T>> to Vec<T> because MaybeUninit<T> has the same
200 // alignment and size as T, so the pointer to the vector allocation
201 // will be compatible.
202 let vec: Option<Vec<Self>> = unsafe {
203 std::mem::transmute(vec)
204 };
205 Ok(vec)
206 } else {
207 Err(IpcStatusCode::Failed)
208 }
209 }
210 }
211
212 /// Callback to deserialize a parcelable element.
213 ///
214 /// # Safety
215 ///
216 /// The opaque array data pointer must be a mutable pointer to an
217 /// `Option<Vec<MaybeUninit<T>>>` with at least enough elements for `index` to be valid
218 /// (zero-based).
219 #[allow(dead_code)]
de_element<T: Deserialize>( parcel: *const ipc_binding::CParcel, array: *mut c_void, index: c_ulong, ) -> bool220 unsafe extern "C" fn de_element<T: Deserialize>(
221 parcel: *const ipc_binding::CParcel,
222 array: *mut c_void,
223 index: c_ulong,
224 ) -> bool {
225 // c_ulong and usize are the same, but we need the explicitly sized version
226 // so the function signature matches what bindgen generates.
227 let index = index as usize;
228
229 let vec = &mut *(array as *mut Option<Vec<MaybeUninit<T>>>);
230 let vec = match vec {
231 Some(v) => v,
232 None => return false,
233 };
234 let parcel = match BorrowedMsgParcel::from_raw(parcel as *mut _) {
235 None => return false,
236 Some(p) => p,
237 };
238 let element = match parcel.read() {
239 Ok(e) => e,
240 Err(_) => return false,
241 };
242 ptr::write(vec[index].as_mut_ptr(), element);
243 true
244 }
245 /// # Safety
246 ///
247 /// All elements in the vector must be properly initialized.
vec_assume_init<T>(vec: Vec<MaybeUninit<T>>) -> Vec<T>248 pub unsafe fn vec_assume_init<T>(vec: Vec<MaybeUninit<T>>) -> Vec<T> {
249 // We can convert from Vec<MaybeUninit<T>> to Vec<T> because MaybeUninit<T>
250 // has the same alignment and size as T, so the pointer to the vector
251 // allocation will be compatible.
252 let mut vec = std::mem::ManuallyDrop::new(vec);
253 Vec::from_raw_parts(
254 vec.as_mut_ptr().cast(),
255 vec.len(),
256 vec.capacity(),
257 )
258 }
259
260 /// # Safety
261 ///
262 /// Ensure that the value pointer is not null
allocate_vec_maybeuninit<T>( value: *mut c_void, len: u32, )263 pub(crate) unsafe fn allocate_vec_maybeuninit<T>(
264 value: *mut c_void,
265 len: u32,
266 ) {
267 let vec = &mut *(value as *mut Option<Vec<MaybeUninit<T>>>);
268 let mut new_vec: Vec<MaybeUninit<T>> = Vec::with_capacity(len as usize);
269
270 // SAFETY: this is safe because the vector contains MaybeUninit elements which can be uninitialized
271 new_vec.set_len(len as usize);
272 ptr::write(vec, Some(new_vec));
273 }