• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }