• 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 super::*;
17 use crate::{ipc_binding, BorrowedMsgParcel, IpcResult, IpcStatusCode, status_result, AsRawPtr};
18 use std::convert::TryInto;
19 use std::mem::MaybeUninit;
20 use std::ffi::{CString};
21 use hilog_rust::{error, hilog, HiLogLabel, LogType};
22 
23 const LOG_LABEL: HiLogLabel = HiLogLabel {
24     log_type: LogType::LogCore,
25     domain: 0xd001510,
26     tag: "RustString16"
27 };
28 
29 /// String16 packed a String type which transfered with C++ std::u16string.
30 pub struct String16(String);
31 
32 impl String16 {
33     /// Create a String16 object with rust String
new(value: &str) -> Self34     pub fn new(value: &str) -> Self {
35         Self(String::from(value))
36     }
37 
38     /// Get packed String of String16
get_string(&self) -> String39     pub fn get_string(&self) -> String {
40         String::from(&self.0)
41     }
42 }
43 
44 impl Serialize for String16 {
serialize(&self, parcel: &mut BorrowedMsgParcel<'_>) -> IpcResult<()>45     fn serialize(&self, parcel: &mut BorrowedMsgParcel<'_>) -> IpcResult<()> {
46         let string = &self.0;
47         // SAFETY: `parcel` always contains a valid pointer to a  `CParcel`
48         let ret = unsafe {
49             ipc_binding::CParcelWriteString16(
50                 parcel.as_mut_raw(),
51                 string.as_ptr() as *const c_char,
52                 string.as_bytes().len().try_into().unwrap()
53             )};
54         status_result::<()>(ret as i32, ())
55     }
56 }
57 
58 impl Deserialize for String16 {
deserialize(parcel: &BorrowedMsgParcel<'_>) -> IpcResult<Self>59     fn deserialize(parcel: &BorrowedMsgParcel<'_>) -> IpcResult<Self> {
60         let mut vec: Option<Vec<u8>> = None;
61         // SAFETY: `parcel` always contains a valid pointer to a  `CParcel`
62         let ok_status = unsafe {
63             ipc_binding::CParcelReadString16(
64                 parcel.as_raw(),
65                 &mut vec as *mut _ as *mut c_void,
66                 allocate_vec_with_buffer::<u8>
67             )
68         };
69 
70         if ok_status {
71             let result = vec.map(|s| {
72                 match String::from_utf8(s) {
73                     Ok(val) => val,
74                     Err(_) => String::from("")
75                 }
76             });
77             if let Some(val) = result {
78                 Ok(Self(val))
79             } else {
80                 error!(LOG_LABEL, "convert native string16 to String fail");
81                 Err(IpcStatusCode::Failed)
82             }
83         } else {
84             error!(LOG_LABEL, "read string16 from native fail");
85             Err(IpcStatusCode::Failed)
86         }
87     }
88 }
89 
90 impl SerArray for String16 {
ser_array(slice: &[Self], parcel: &mut BorrowedMsgParcel<'_>) -> IpcResult<()>91     fn ser_array(slice: &[Self], parcel: &mut BorrowedMsgParcel<'_>) -> IpcResult<()> {
92         // SAFETY: `parcel` always contains a valid pointer to a  `CParcel`
93         let ret = unsafe {
94             ipc_binding::CParcelWriteString16Array(
95                 parcel.as_mut_raw(),
96                 slice.as_ptr() as *const c_void,
97                 slice.len().try_into().unwrap(),
98                 on_string16_writer,
99             )
100         };
101         status_result::<()>(ret as i32, ())
102     }
103 }
104 
105 impl DeArray for String16 {
de_array(parcel: &BorrowedMsgParcel<'_>) -> IpcResult<Option<Vec<Self>>>106     fn de_array(parcel: &BorrowedMsgParcel<'_>) -> IpcResult<Option<Vec<Self>>> {
107         let mut vec: Option<Vec<MaybeUninit<Self>>> = None;
108         // SAFETY: `parcel` always contains a valid pointer to a  `CParcel`
109         // `allocate_vec<T>` expects the opaque pointer to
110         // be of type `*mut Option<Vec<MaybeUninit<T>>>`, so `&mut vec` is
111         // correct for it.
112         let ok_status = unsafe {
113             ipc_binding::CParcelReadString16Array(
114                 parcel.as_raw(),
115                 &mut vec as *mut _ as *mut c_void,
116                 on_string16_reader,
117             )
118         };
119         if ok_status {
120             // SAFETY: all the MaybeUninits are now properly initialized.
121             let vec: Option<Vec<Self>> = unsafe {
122                 vec.map(|vec| vec_assume_init(vec))
123             };
124             Ok(vec)
125         } else {
126             error!(LOG_LABEL, "read string16 from native fail");
127             Err(IpcStatusCode::Failed)
128         }
129     }
130 }
131 /// Callback to serialize a String16 array to c++ std::vector<std::u16string>.
132 ///
133 /// # Safety:
134 ///
135 /// We are relying on c interface to not overrun our slice. As long
136 /// as it doesn't provide an index larger than the length of the original
137 /// slice in ser_array, this operation is safe. The index provided
138 /// is zero-based.
139 #[allow(dead_code)]
on_string16_writer( array: *const c_void, value: *mut c_void, len: u32, ) -> bool140 pub unsafe extern "C" fn on_string16_writer(
141     array: *const c_void, // C++ vector pointer
142     value: *mut c_void, // Rust slice pointer
143     len: u32,
144 ) -> bool {
145     if len == 0 {
146         return false;
147     }
148     let len = len as usize;
149     let slice: &[String16] = std::slice::from_raw_parts(value.cast(), len);
150 
151     for item in slice.iter().take(len) {
152         // SAFETY:
153         let ret = unsafe {
154             ipc_binding::CParcelWritU16stringElement(
155                 array,
156                 item.0.as_ptr() as *const c_char,
157                 item.0.as_bytes().len().try_into().unwrap())
158         };
159         if !ret {
160             return false;
161         }
162     }
163     true
164 }
165 
166 /// Callback to deserialize a String element in Vector<String16>.
167 ///
168 /// # Safety:
169 ///
170 /// The opaque array data pointer must be a mutable pointer to an
171 /// `Option<Vec<MaybeUninit<T>>>` with at least enough elements for `index` to be valid
172 /// (zero-based).
173 #[allow(dead_code)]
on_string16_reader( data: *const c_void, value: *mut c_void, len: u32, ) -> bool174 unsafe extern "C" fn on_string16_reader(
175     data: *const c_void, // C++ vector pointer
176     value: *mut c_void, // Rust vector pointer
177     len: u32, // C++ vector length
178 ) -> bool {
179     // SAFETY:
180     // Allocate Vec<String16> capacity, data_len will set correctly by vec.push().
181     unsafe { allocate_vec_maybeuninit::<String16>(value, 0) };
182     let vec = &mut *(value as *mut Option<Vec<MaybeUninit<String16>>>);
183     for index in 0..len {
184         let mut vec_u16: Option<Vec<u16>> = None;
185         // SAFETY: The length of the index will not exceed the range,
186         // as the traversal range is the pointer length of the data passed from the C++side
187         let ok_status = unsafe {
188             ipc_binding::CParcelReadString16Element(
189                 index,
190                 data,
191                 &mut vec_u16 as *mut _ as *mut c_void,
192                 allocate_vec_with_buffer::<u16>
193             )
194         };
195         if ok_status {
196             if let Ok(string) = vec_u16_to_string(vec_u16) {
197                 if let Some(new_vec) = vec {
198                     new_vec.push(MaybeUninit::new(String16::new(string.as_str())));
199                 } else {
200                     error!(LOG_LABEL, "on_string_reader allocate vec failed");
201                     return false;
202                 }
203             } else {
204                 error!(LOG_LABEL, "on_string_reader vec_to_string failed");
205                 return false;
206             }
207         } else {
208             return false;
209         }
210     }
211     true
212 }
213