• 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::{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 }