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