1 /*
2  * Copyright (c) 2023 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::c_adapter::*;
17 use crate::ipc_conn;
18 use crate::service_impl::{cloud_service, types};
19 use std::collections::HashMap;
20 use std::ffi::{c_int, c_uchar, c_uint, c_void};
21 use std::ptr::null_mut;
22 
23 pub type OhCloudExtVector = SafeCffiWrapper<VectorCffi>;
24 pub type OhCloudExtHashMap = SafeCffiWrapper<HashMapCffi>;
25 
26 /// Value type enum in C. Used to represent returning type value, so C side can cast its pointer.
27 #[repr(C)]
28 #[allow(non_camel_case_types, clippy::upper_case_acronyms)]
29 #[derive(PartialEq, Debug)]
30 pub enum OhCloudExtRustType {
31     NULL = 0,
32     U32,
33     I32,
34     STRING,
35     VALUE,
36     VALUE_BUCKET,
37     DATABASE,
38     TABLE,
39     FIELD,
40     RELATION,
41     RELATION_SET,
42     CLOUD_ASSET,
43     APP_INFO,
44     VEC_U32,
45     VEC_STRING,
46     VEC_DATABASE,
47     HASHMAP_VALUE,
48 }
49 
50 /// Vector enum in C side to adapt Vector generic types.
51 pub enum VectorCffi {
52     I32(Vec<i32>),
53     U32(Vec<u32>),
54     String(Vec<String>),
55     Value(Vec<types::Value>),
56     ValueBucket(Vec<ipc_conn::ValueBucket>),
57     Database(Vec<types::Database>),
58     Table(Vec<types::Table>),
59     Field(Vec<types::Field>),
60     RelationSet(Vec<cloud_service::RelationSet>),
61     CloudAsset(Vec<ipc_conn::CloudAsset>),
62     AppInfo(Vec<cloud_service::AppInfo>),
63     VecU32(Vec<Vec<u32>>),
64     VecString(Vec<Vec<String>>),
65     VecDatabase(Vec<Vec<types::Database>>),
66     HashMapValue(Vec<HashMap<String, types::Value>>),
67 }
68 
69 /// Hashmap enum in C side to adapt Vector generic types. String as the key, enum type only
70 /// marks value type.
71 pub enum HashMapCffi {
72     U32(HashMap<String, u32>),
73     String(HashMap<String, String>),
74     Value(HashMap<String, types::Value>),
75     Table(HashMap<String, types::Table>),
76     RelationSet(HashMap<String, cloud_service::RelationSet>),
77     AppInfo(HashMap<String, cloud_service::AppInfo>),
78     VecU32(HashMap<String, Vec<u32>>),
79     VecString(HashMap<String, Vec<String>>),
80     VecDatabase(HashMap<String, Vec<types::Database>>),
81 }
82 
83 /// Create a Vector enum according to ValueType.
84 ///
85 /// # Safety
86 /// For other functions relating to Vector usage, the pointer of Vector should be valid through
87 /// the lifetime of these function calls. Also, when using String values, users should guarantee
88 /// that String doesn't contain non-UTF8 literals, and the length passed in is valid.
89 ///
90 /// These two requirements need to be fulfilled to avoid memory issues and undefined behaviors.
91 #[no_mangle]
OhCloudExtVectorNew(typ: OhCloudExtRustType) -> *mut OhCloudExtVector92 pub unsafe extern "C" fn OhCloudExtVectorNew(typ: OhCloudExtRustType) -> *mut OhCloudExtVector {
93     let vec = match typ {
94         OhCloudExtRustType::I32 => VectorCffi::I32(vec![]),
95         OhCloudExtRustType::U32 => VectorCffi::U32(vec![]),
96         OhCloudExtRustType::STRING => VectorCffi::String(vec![]),
97         OhCloudExtRustType::VALUE => VectorCffi::Value(vec![]),
98         OhCloudExtRustType::VALUE_BUCKET => VectorCffi::ValueBucket(vec![]),
99         OhCloudExtRustType::DATABASE => VectorCffi::Database(vec![]),
100         OhCloudExtRustType::TABLE => VectorCffi::Table(vec![]),
101         OhCloudExtRustType::FIELD => VectorCffi::Field(vec![]),
102         OhCloudExtRustType::RELATION_SET => VectorCffi::RelationSet(vec![]),
103         OhCloudExtRustType::CLOUD_ASSET => VectorCffi::CloudAsset(vec![]),
104         OhCloudExtRustType::APP_INFO => VectorCffi::AppInfo(vec![]),
105         OhCloudExtRustType::VEC_U32 => VectorCffi::VecU32(vec![]),
106         OhCloudExtRustType::VEC_STRING => VectorCffi::VecString(vec![]),
107         OhCloudExtRustType::VEC_DATABASE => VectorCffi::VecDatabase(vec![]),
108         OhCloudExtRustType::HASHMAP_VALUE => VectorCffi::HashMapValue(vec![]),
109         // Not supported
110         _ => return null_mut(),
111     };
112     OhCloudExtVector::new(vec, SafetyCheckId::Vector).into_ptr()
113 }
114 
115 /// Get ValueType of the Vector pointer.
116 ///
117 /// # Safety
118 /// Pointer passed in should be valid during the whole lifetime of this function, or memory issues
119 /// might happen.
120 #[no_mangle]
OhCloudExtVectorGetValueTyp( vector: *const OhCloudExtVector, ) -> OhCloudExtRustType121 pub unsafe extern "C" fn OhCloudExtVectorGetValueTyp(
122     vector: *const OhCloudExtVector,
123 ) -> OhCloudExtRustType {
124     let vector = match OhCloudExtVector::get_inner_ref(vector, SafetyCheckId::Vector) {
125         None => return OhCloudExtRustType::NULL,
126         Some(v) => v,
127     };
128     match vector {
129         VectorCffi::I32(_) => OhCloudExtRustType::I32,
130         VectorCffi::U32(_) => OhCloudExtRustType::U32,
131         VectorCffi::String(_) => OhCloudExtRustType::STRING,
132         VectorCffi::Value(_) => OhCloudExtRustType::VALUE,
133         VectorCffi::ValueBucket(_) => OhCloudExtRustType::VALUE_BUCKET,
134         VectorCffi::Database(_) => OhCloudExtRustType::DATABASE,
135         VectorCffi::Table(_) => OhCloudExtRustType::TABLE,
136         VectorCffi::Field(_) => OhCloudExtRustType::FIELD,
137         VectorCffi::RelationSet(_) => OhCloudExtRustType::RELATION_SET,
138         VectorCffi::CloudAsset(_) => OhCloudExtRustType::CLOUD_ASSET,
139         VectorCffi::AppInfo(_) => OhCloudExtRustType::APP_INFO,
140         VectorCffi::VecU32(_) => OhCloudExtRustType::VEC_U32,
141         VectorCffi::VecString(_) => OhCloudExtRustType::VEC_STRING,
142         VectorCffi::VecDatabase(_) => OhCloudExtRustType::VEC_DATABASE,
143         VectorCffi::HashMapValue(_) => OhCloudExtRustType::HASHMAP_VALUE,
144     }
145 }
146 
147 /// Push value into the Vector pointer. If the value pushed is allocated in the Rust side before,
148 /// pushing them means to transfer their management to the Vector, so no more free is needed.
149 ///
150 /// # Safety
151 /// Pointer passed in should be valid during the whole lifetime of this function, or memory issues
152 /// might happen. Besides, value pointer should also be in the same type as the type used in
153 /// initialization of the Vector.
154 #[no_mangle]
OhCloudExtVectorPush( vector: *mut OhCloudExtVector, value: *mut c_void, value_len: c_uint, ) -> c_int155 pub unsafe extern "C" fn OhCloudExtVectorPush(
156     vector: *mut OhCloudExtVector,
157     value: *mut c_void,
158     value_len: c_uint,
159 ) -> c_int {
160     if vector.is_null() || value.is_null() {
161         return ERRNO_NULLPTR;
162     }
163 
164     let vector = match OhCloudExtVector::get_inner_mut(vector, SafetyCheckId::Vector) {
165         None => return ERRNO_WRONG_TYPE,
166         Some(v) => v,
167     };
168 
169     match vector {
170         VectorCffi::I32(vec) => {
171             let ptr = value as *mut i32;
172             vec.push(*ptr);
173         }
174         VectorCffi::U32(vec) => {
175             let ptr = value as *mut u32;
176             vec.push(*ptr);
177         }
178         VectorCffi::String(vec) => {
179             let str = char_ptr_to_string(value as *const c_uchar, value_len);
180             vec.push(str);
181         }
182         VectorCffi::Value(vec) => {
183             let val = match OhCloudExtValue::get_inner(value as *mut _, SafetyCheckId::Value) {
184                 None => return ERRNO_WRONG_TYPE,
185                 Some(v) => v,
186             };
187             vec.push(val);
188         }
189         VectorCffi::ValueBucket(vec) => {
190             let vb =
191                 match OhCloudExtValueBucket::get_inner(value as *mut _, SafetyCheckId::ValueBucket)
192                 {
193                     None => return ERRNO_WRONG_TYPE,
194                     Some(v) => v,
195                 };
196             vec.push(vb);
197         }
198         VectorCffi::Database(vec) => {
199             let db = match OhCloudExtDatabase::get_inner(value as *mut _, SafetyCheckId::Database) {
200                 None => return ERRNO_WRONG_TYPE,
201                 Some(v) => v,
202             };
203             vec.push(db);
204         }
205         VectorCffi::Table(vec) => {
206             let val = match OhCloudExtTable::get_inner(value as *mut _, SafetyCheckId::Table) {
207                 None => return ERRNO_WRONG_TYPE,
208                 Some(v) => v,
209             };
210             vec.push(val);
211         }
212         VectorCffi::Field(vec) => {
213             let fd = match OhCloudExtField::get_inner(value as *mut _, SafetyCheckId::Field) {
214                 None => return ERRNO_WRONG_TYPE,
215                 Some(v) => v,
216             };
217             vec.push(fd);
218         }
219         VectorCffi::RelationSet(vec) => {
220             let val =
221                 match OhCloudExtRelationSet::get_inner(value as *mut _, SafetyCheckId::RelationSet)
222                 {
223                     None => return ERRNO_WRONG_TYPE,
224                     Some(v) => v,
225                 };
226             vec.push(val);
227         }
228         VectorCffi::CloudAsset(vec) => {
229             let cloud_asset =
230                 match OhCloudExtCloudAsset::get_inner(value as *mut _, SafetyCheckId::CloudAsset) {
231                     None => return ERRNO_WRONG_TYPE,
232                     Some(v) => v,
233                 };
234             vec.push(cloud_asset);
235         }
236         VectorCffi::AppInfo(vec) => {
237             let val = match OhCloudExtAppInfo::get_inner(value as *mut _, SafetyCheckId::AppInfo) {
238                 None => return ERRNO_WRONG_TYPE,
239                 Some(v) => v,
240             };
241             vec.push(val);
242         }
243         VectorCffi::VecU32(vec) => {
244             let vec_struct =
245                 match OhCloudExtVector::get_inner(value as *mut _, SafetyCheckId::Vector) {
246                     None => return ERRNO_WRONG_TYPE,
247                     Some(v) => v,
248                 };
249             match vec_struct {
250                 VectorCffi::U32(v) => vec.push(v),
251                 _ => return ERRNO_INVALID_INPUT_TYPE,
252             }
253         }
254         VectorCffi::VecString(vec) => {
255             let vec_struct =
256                 match OhCloudExtVector::get_inner(value as *mut _, SafetyCheckId::Vector) {
257                     None => return ERRNO_WRONG_TYPE,
258                     Some(v) => v,
259                 };
260             match vec_struct {
261                 VectorCffi::String(v) => vec.push(v),
262                 _ => return ERRNO_INVALID_INPUT_TYPE,
263             }
264         }
265         VectorCffi::VecDatabase(vec) => {
266             let vec_struct =
267                 match OhCloudExtVector::get_inner(value as *mut _, SafetyCheckId::Vector) {
268                     None => return ERRNO_WRONG_TYPE,
269                     Some(v) => v,
270                 };
271             match vec_struct {
272                 VectorCffi::Database(v) => vec.push(v),
273                 _ => return ERRNO_INVALID_INPUT_TYPE,
274             }
275         }
276         VectorCffi::HashMapValue(vec) => {
277             let map = match OhCloudExtHashMap::get_inner(value as *mut _, SafetyCheckId::HashMap) {
278                 None => return ERRNO_WRONG_TYPE,
279                 Some(v) => v,
280             };
281             match map {
282                 HashMapCffi::Value(m) => vec.push(m),
283                 _ => return ERRNO_INVALID_INPUT_TYPE,
284             }
285         }
286     }
287     ERRNO_SUCCESS
288 }
289 
290 /// Get value from the Vector pointer. If returning type is not raw C type
291 /// pointer, these pointers should be freed by corresponding free functions.
292 ///
293 /// # Safety
294 /// Pointer passed in should be valid during the whole lifetime of this function, or memory issues
295 /// might happen. Besides, value pointer should also be interpreted as same as the type
296 /// used in initialization of the Vector.
297 #[no_mangle]
OhCloudExtVectorGet( vector: *const OhCloudExtVector, index: usize, value: *mut *const c_void, value_len: *mut c_uint, ) -> c_int298 pub unsafe extern "C" fn OhCloudExtVectorGet(
299     vector: *const OhCloudExtVector,
300     index: usize,
301     value: *mut *const c_void,
302     value_len: *mut c_uint,
303 ) -> c_int {
304     macro_rules! get_content {
305         ($vec: ident, $index: ident, $value: ident) => {
306             if $index < $vec.len() {
307                 *$value = (&$vec[index]) as *const _ as *const c_void;
308             } else {
309                 return ERRNO_OUT_OF_RANGE;
310             }
311         };
312     }
313 
314     macro_rules! get_content_clone {
315         ($vec: ident, $index: ident, $value: ident, $typ: ident, $id: ident) => {
316             if $index < $vec.len() {
317                 *$value =
318                     $typ::new($vec[index].clone(), SafetyCheckId::$id).into_ptr() as *const c_void;
319             } else {
320                 return ERRNO_OUT_OF_RANGE;
321             }
322         };
323     }
324 
325     if vector.is_null() || value.is_null() || value_len.is_null() {
326         return ERRNO_NULLPTR;
327     }
328 
329     let vector = match OhCloudExtVector::get_inner_ref(vector, SafetyCheckId::Vector) {
330         None => return ERRNO_WRONG_TYPE,
331         Some(v) => v,
332     };
333 
334     match vector {
335         VectorCffi::I32(vec) => get_content!(vec, index, value),
336         VectorCffi::U32(vec) => get_content!(vec, index, value),
337         VectorCffi::String(vec) => {
338             if index < vec.len() {
339                 *value = vec[index].as_ptr() as *const c_void;
340                 *value_len = vec[index].len() as c_uint;
341             } else {
342                 return ERRNO_OUT_OF_RANGE;
343             }
344         }
345         VectorCffi::Value(vec) => get_content_clone!(vec, index, value, OhCloudExtValue, Value),
346         VectorCffi::ValueBucket(vec) => {
347             get_content_clone!(vec, index, value, OhCloudExtValueBucket, ValueBucket)
348         }
349         VectorCffi::Database(vec) => {
350             get_content_clone!(vec, index, value, OhCloudExtDatabase, Database)
351         }
352         VectorCffi::Table(vec) => get_content_clone!(vec, index, value, OhCloudExtTable, Table),
353         VectorCffi::Field(vec) => get_content_clone!(vec, index, value, OhCloudExtField, Field),
354         VectorCffi::RelationSet(vec) => {
355             get_content_clone!(vec, index, value, OhCloudExtRelationSet, RelationSet)
356         }
357         VectorCffi::CloudAsset(vec) => {
358             get_content_clone!(vec, index, value, OhCloudExtCloudAsset, CloudAsset)
359         }
360         VectorCffi::AppInfo(vec) => {
361             get_content_clone!(vec, index, value, OhCloudExtAppInfo, AppInfo)
362         }
363         VectorCffi::VecU32(vec) => {
364             if index < vec.len() {
365                 let src = &vec[index];
366                 *value = OhCloudExtVector::new(VectorCffi::U32(src.clone()), SafetyCheckId::Vector)
367                     .into_ptr() as *const c_void;
368             } else {
369                 return ERRNO_OUT_OF_RANGE;
370             }
371         }
372         VectorCffi::VecString(vec) => {
373             if index < vec.len() {
374                 let src = &vec[index];
375                 *value =
376                     OhCloudExtVector::new(VectorCffi::String(src.clone()), SafetyCheckId::Vector)
377                         .into_ptr() as *const c_void;
378             } else {
379                 return ERRNO_OUT_OF_RANGE;
380             }
381         }
382         VectorCffi::VecDatabase(vec) => {
383             if index < vec.len() {
384                 let src = &vec[index];
385                 *value =
386                     OhCloudExtVector::new(VectorCffi::Database(src.clone()), SafetyCheckId::Vector)
387                         .into_ptr() as *const c_void;
388             } else {
389                 return ERRNO_OUT_OF_RANGE;
390             }
391         }
392         VectorCffi::HashMapValue(vec) => {
393             if index < vec.len() {
394                 let src = &vec[index];
395                 let mut inner = HashMap::new();
396                 for (key, value) in src {
397                     inner.insert(key.clone(), value.clone());
398                 }
399                 *value = OhCloudExtHashMap::new(HashMapCffi::Value(inner), SafetyCheckId::HashMap)
400                     .into_ptr() as *const c_void;
401             } else {
402                 return ERRNO_OUT_OF_RANGE;
403             }
404         }
405     }
406     ERRNO_SUCCESS
407 }
408 
409 /// Get length of a Vector pointer.
410 ///
411 /// # Safety
412 /// Pointer passed in should be valid during the whole lifetime of this function, or memory issues
413 /// might happen.
414 #[no_mangle]
OhCloudExtVectorGetLength( vector: *const OhCloudExtVector, len: *mut c_uint, ) -> c_int415 pub unsafe extern "C" fn OhCloudExtVectorGetLength(
416     vector: *const OhCloudExtVector,
417     len: *mut c_uint,
418 ) -> c_int {
419     if vector.is_null() || len.is_null() {
420         return ERRNO_NULLPTR;
421     }
422     let vector = match OhCloudExtVector::get_inner_ref(vector, SafetyCheckId::Vector) {
423         None => return ERRNO_WRONG_TYPE,
424         Some(v) => v,
425     };
426     match vector {
427         VectorCffi::I32(vec) => *len = vec.len() as c_uint,
428         VectorCffi::U32(vec) => *len = vec.len() as c_uint,
429         VectorCffi::String(vec) => *len = vec.len() as c_uint,
430         VectorCffi::Value(vec) => *len = vec.len() as c_uint,
431         VectorCffi::ValueBucket(vec) => *len = vec.len() as c_uint,
432         VectorCffi::Database(vec) => *len = vec.len() as c_uint,
433         VectorCffi::Table(vec) => *len = vec.len() as c_uint,
434         VectorCffi::Field(vec) => *len = vec.len() as c_uint,
435         VectorCffi::RelationSet(vec) => *len = vec.len() as c_uint,
436         VectorCffi::CloudAsset(vec) => *len = vec.len() as c_uint,
437         VectorCffi::AppInfo(vec) => *len = vec.len() as c_uint,
438         VectorCffi::VecU32(vec) => *len = vec.len() as c_uint,
439         VectorCffi::VecString(vec) => *len = vec.len() as c_uint,
440         VectorCffi::VecDatabase(vec) => *len = vec.len() as c_uint,
441         VectorCffi::HashMapValue(vec) => *len = vec.len() as c_uint,
442     }
443     ERRNO_SUCCESS
444 }
445 
446 /// Free a Vector pointer.
447 ///
448 /// # Safety
449 /// Pointer passed in should be valid during the whole lifetime of this function, or memory issues
450 /// might happen.
451 #[no_mangle]
OhCloudExtVectorFree(vector: *mut OhCloudExtVector)452 pub unsafe extern "C" fn OhCloudExtVectorFree(vector: *mut OhCloudExtVector) {
453     let _ = OhCloudExtVector::from_ptr(vector, SafetyCheckId::Vector);
454 }
455 
456 /// Initialize a HashMap enum by its ValueType. The key type is fixed to be String.
457 ///
458 /// # Safety
459 /// For other functions relating to HashMap usage, the pointer of HashMap should be valid through
460 /// the lifetime of these function calls. Also, when using String values, users should guarantee
461 /// that String doesn't contain non-UTF8 literals, and the length passed in is valid.
462 ///
463 /// These two requirements need to be fulfilled to avoid memory issues and undefined behaviors.
464 #[no_mangle]
OhCloudExtHashMapNew( value_type: OhCloudExtRustType, ) -> *mut OhCloudExtHashMap465 pub unsafe extern "C" fn OhCloudExtHashMapNew(
466     value_type: OhCloudExtRustType,
467 ) -> *mut OhCloudExtHashMap {
468     let map = match value_type {
469         OhCloudExtRustType::U32 => HashMapCffi::U32(HashMap::default()),
470         OhCloudExtRustType::STRING => HashMapCffi::String(HashMap::default()),
471         OhCloudExtRustType::VALUE => HashMapCffi::Value(HashMap::default()),
472         OhCloudExtRustType::TABLE => HashMapCffi::Table(HashMap::default()),
473         OhCloudExtRustType::RELATION => HashMapCffi::RelationSet(HashMap::default()),
474         OhCloudExtRustType::APP_INFO => HashMapCffi::AppInfo(HashMap::default()),
475         OhCloudExtRustType::VEC_U32 => HashMapCffi::VecU32(HashMap::default()),
476         OhCloudExtRustType::VEC_STRING => HashMapCffi::VecString(HashMap::default()),
477         OhCloudExtRustType::VEC_DATABASE => HashMapCffi::VecDatabase(HashMap::default()),
478         // Not supported
479         _ => return null_mut(),
480     };
481     OhCloudExtHashMap::new(map, SafetyCheckId::HashMap).into_ptr()
482 }
483 
484 /// Get key type of a Hashmap pointer.
485 ///
486 /// # Safety
487 /// Pointer passed in should be valid during the whole lifetime of this function, or memory issues
488 /// might happen.
489 #[no_mangle]
OhCloudExtHashMapGetKeyTyp( hash_map: *const OhCloudExtHashMap, ) -> OhCloudExtRustType490 pub unsafe extern "C" fn OhCloudExtHashMapGetKeyTyp(
491     hash_map: *const OhCloudExtHashMap,
492 ) -> OhCloudExtRustType {
493     if hash_map.is_null() {
494         OhCloudExtRustType::NULL
495     } else {
496         OhCloudExtRustType::STRING
497     }
498 }
499 
500 /// Get value type of a Hashmap pointer.
501 ///
502 /// # Safety
503 /// Pointer passed in should be valid during the whole lifetime of this function, or memory issues
504 /// might happen.
505 #[no_mangle]
OhCloudExtHashMapGetValueTyp( hash_map: *const OhCloudExtHashMap, ) -> OhCloudExtRustType506 pub unsafe extern "C" fn OhCloudExtHashMapGetValueTyp(
507     hash_map: *const OhCloudExtHashMap,
508 ) -> OhCloudExtRustType {
509     if hash_map.is_null() {
510         return OhCloudExtRustType::NULL;
511     }
512     let hash_map = match OhCloudExtHashMap::get_inner_ref(hash_map, SafetyCheckId::HashMap) {
513         None => return OhCloudExtRustType::NULL,
514         Some(v) => v,
515     };
516     match hash_map {
517         HashMapCffi::U32(_) => OhCloudExtRustType::U32,
518         HashMapCffi::String(_) => OhCloudExtRustType::STRING,
519         HashMapCffi::Value(_) => OhCloudExtRustType::VALUE,
520         HashMapCffi::Table(_) => OhCloudExtRustType::TABLE,
521         HashMapCffi::RelationSet(_) => OhCloudExtRustType::RELATION,
522         HashMapCffi::AppInfo(_) => OhCloudExtRustType::APP_INFO,
523         HashMapCffi::VecU32(_) => OhCloudExtRustType::VEC_U32,
524         HashMapCffi::VecString(_) => OhCloudExtRustType::VEC_STRING,
525         HashMapCffi::VecDatabase(_) => OhCloudExtRustType::VEC_DATABASE,
526     }
527 }
528 
529 /// Get length of a Hashmap pointer.
530 ///
531 /// # Safety
532 /// Pointer passed in should be valid during the whole lifetime of this function, or memory issues
533 /// might happen.
534 #[no_mangle]
OhCloudExtHashMapGetLength( hash_map: *const OhCloudExtHashMap, len: *mut c_uint, ) -> c_int535 pub unsafe extern "C" fn OhCloudExtHashMapGetLength(
536     hash_map: *const OhCloudExtHashMap,
537     len: *mut c_uint,
538 ) -> c_int {
539     if hash_map.is_null() || len.is_null() {
540         return ERRNO_NULLPTR;
541     }
542     let hash_map = match OhCloudExtHashMap::get_inner_ref(hash_map, SafetyCheckId::HashMap) {
543         None => return ERRNO_WRONG_TYPE,
544         Some(v) => v,
545     };
546     match hash_map {
547         HashMapCffi::U32(map) => *len = map.len() as c_uint,
548         HashMapCffi::String(map) => *len = map.len() as c_uint,
549         HashMapCffi::Value(map) => *len = map.len() as c_uint,
550         HashMapCffi::Table(map) => *len = map.len() as c_uint,
551         HashMapCffi::RelationSet(map) => *len = map.len() as c_uint,
552         HashMapCffi::AppInfo(map) => *len = map.len() as c_uint,
553         HashMapCffi::VecU32(map) => *len = map.len() as c_uint,
554         HashMapCffi::VecString(map) => *len = map.len() as c_uint,
555         HashMapCffi::VecDatabase(map) => *len = map.len() as c_uint,
556     }
557     ERRNO_SUCCESS
558 }
559 
560 /// Insert key, value pairs into the Hashmap pointer. If the value pushed is allocated in the Rust
561 /// side before, pushing them means to transfer their management to the Hashmap, so no more free
562 /// is needed.
563 ///
564 /// # Safety
565 /// Pointer passed in should be valid during the whole lifetime of this function, or memory issues
566 /// might happen. Besides, value and key pointers should also be in the same types as the types
567 /// used in initialization of the HashMap.
568 #[no_mangle]
OhCloudExtHashMapInsert( hash_map: *mut OhCloudExtHashMap, key: *const c_uchar, key_len: c_uint, value: *mut c_void, value_len: c_uint, ) -> c_int569 pub unsafe extern "C" fn OhCloudExtHashMapInsert(
570     hash_map: *mut OhCloudExtHashMap,
571     key: *const c_uchar,
572     key_len: c_uint,
573     value: *mut c_void,
574     value_len: c_uint,
575 ) -> c_int {
576     if hash_map.is_null() || key.is_null() || value.is_null() {
577         return ERRNO_NULLPTR;
578     }
579     let hash_map = match OhCloudExtHashMap::get_inner_mut(hash_map, SafetyCheckId::HashMap) {
580         None => return ERRNO_WRONG_TYPE,
581         Some(v) => v,
582     };
583     let key = char_ptr_to_string(key as *const c_uchar, key_len);
584     match hash_map {
585         HashMapCffi::U32(map) => {
586             let ptr = value as *mut u32;
587             map.insert(key, *ptr);
588         }
589         HashMapCffi::String(map) => {
590             let value = char_ptr_to_string(value as *const c_uchar, value_len);
591             map.insert(key, value);
592         }
593         HashMapCffi::Value(map) => {
594             let val = match OhCloudExtValue::get_inner(value as *mut _, SafetyCheckId::Value) {
595                 None => return ERRNO_WRONG_TYPE,
596                 Some(v) => v,
597             };
598             map.insert(key, val);
599         }
600         HashMapCffi::Table(map) => {
601             let val = match OhCloudExtTable::get_inner(value as *mut _, SafetyCheckId::Table) {
602                 None => return ERRNO_WRONG_TYPE,
603                 Some(v) => v,
604             };
605             map.insert(key, val);
606         }
607         HashMapCffi::RelationSet(map) => {
608             let val =
609                 match OhCloudExtRelationSet::get_inner(value as *mut _, SafetyCheckId::RelationSet)
610                 {
611                     None => return ERRNO_WRONG_TYPE,
612                     Some(v) => v,
613                 };
614             map.insert(key, val);
615         }
616         HashMapCffi::AppInfo(map) => {
617             let val = match OhCloudExtAppInfo::get_inner(value as *mut _, SafetyCheckId::AppInfo) {
618                 None => return ERRNO_WRONG_TYPE,
619                 Some(v) => v,
620             };
621             map.insert(key, val);
622         }
623         HashMapCffi::VecU32(map) => {
624             let val = match OhCloudExtVector::get_inner(value as *mut _, SafetyCheckId::Vector) {
625                 None => return ERRNO_WRONG_TYPE,
626                 Some(v) => v,
627             };
628             match val {
629                 VectorCffi::U32(vec) => map.insert(key, vec),
630                 _ => return ERRNO_INVALID_INPUT_TYPE,
631             };
632         }
633         HashMapCffi::VecString(map) => {
634             let val = match OhCloudExtVector::get_inner(value as *mut _, SafetyCheckId::Vector) {
635                 None => return ERRNO_WRONG_TYPE,
636                 Some(v) => v,
637             };
638             match val {
639                 VectorCffi::String(vec) => map.insert(key, vec),
640                 _ => return ERRNO_INVALID_INPUT_TYPE,
641             };
642         }
643         HashMapCffi::VecDatabase(map) => {
644             let val = match OhCloudExtVector::get_inner(value as *mut _, SafetyCheckId::Vector) {
645                 None => return ERRNO_WRONG_TYPE,
646                 Some(v) => v,
647             };
648             match val {
649                 VectorCffi::Database(vec) => map.insert(key, vec),
650                 _ => return ERRNO_INVALID_INPUT_TYPE,
651             };
652         }
653     }
654     ERRNO_SUCCESS
655 }
656 
657 /// Get key, value pair from the Hashmap pointer. The returning type is `Vector`, and should be
658 /// freed by `VectorFree`.
659 ///
660 /// # Safety
661 /// Pointer passed in should be valid during the whole lifetime of this function, or memory issues
662 /// might happen. Besides, value and key pointer should also be interpreted as same types as the
663 /// types used in initialization of the HashMap.
664 #[no_mangle]
OhCloudExtHashMapIterGetKeyValuePair( hash_map: *const OhCloudExtHashMap, key: *mut *const OhCloudExtVector, value: *mut *const OhCloudExtVector, ) -> c_int665 pub unsafe extern "C" fn OhCloudExtHashMapIterGetKeyValuePair(
666     hash_map: *const OhCloudExtHashMap,
667     key: *mut *const OhCloudExtVector,
668     value: *mut *const OhCloudExtVector,
669 ) -> c_int {
670     if hash_map.is_null() || key.is_null() || value.is_null() {
671         return ERRNO_NULLPTR;
672     }
673     let hash_map = match OhCloudExtHashMap::get_inner_ref(hash_map, SafetyCheckId::HashMap) {
674         None => return ERRNO_WRONG_TYPE,
675         Some(v) => v,
676     };
677     match hash_map {
678         HashMapCffi::U32(map) => {
679             let key_vec = map.keys().cloned().collect();
680             let value_vec: Vec<u32> = map.values().cloned().collect();
681 
682             *key = OhCloudExtVector::new(VectorCffi::String(key_vec), SafetyCheckId::Vector)
683                 .into_ptr() as *const OhCloudExtVector;
684             *value = OhCloudExtVector::new(VectorCffi::U32(value_vec), SafetyCheckId::Vector)
685                 .into_ptr() as *const OhCloudExtVector;
686         }
687         HashMapCffi::String(map) => {
688             let key_vec = map.keys().cloned().collect();
689             let value_vec: Vec<String> = map.values().cloned().collect();
690 
691             *key = OhCloudExtVector::new(VectorCffi::String(key_vec), SafetyCheckId::Vector)
692                 .into_ptr() as *const OhCloudExtVector;
693             *value = OhCloudExtVector::new(VectorCffi::String(value_vec), SafetyCheckId::Vector)
694                 .into_ptr() as *const OhCloudExtVector;
695         }
696         HashMapCffi::Value(map) => {
697             let key_vec: Vec<String> = map.keys().cloned().collect();
698             let value_vec: Vec<types::Value> = map.values().cloned().collect();
699 
700             *key = OhCloudExtVector::new(VectorCffi::String(key_vec), SafetyCheckId::Vector)
701                 .into_ptr() as *const OhCloudExtVector;
702             *value = OhCloudExtVector::new(VectorCffi::Value(value_vec), SafetyCheckId::Vector)
703                 .into_ptr() as *const OhCloudExtVector;
704         }
705         HashMapCffi::Table(map) => {
706             let key_vec: Vec<String> = map.keys().cloned().collect();
707             let mut value_vec = vec![];
708             for src in map.values() {
709                 value_vec.push(src.clone());
710             }
711 
712             *key = OhCloudExtVector::new(VectorCffi::String(key_vec), SafetyCheckId::Vector)
713                 .into_ptr() as *const OhCloudExtVector;
714             *value = OhCloudExtVector::new(VectorCffi::Table(value_vec), SafetyCheckId::Vector)
715                 .into_ptr() as *const OhCloudExtVector;
716         }
717         HashMapCffi::RelationSet(map) => {
718             let key_vec: Vec<String> = map.keys().cloned().collect();
719             let mut value_vec = vec![];
720             for src in map.values() {
721                 value_vec.push(src.clone());
722             }
723 
724             *key = OhCloudExtVector::new(VectorCffi::String(key_vec), SafetyCheckId::Vector)
725                 .into_ptr() as *const OhCloudExtVector;
726             *value =
727                 OhCloudExtVector::new(VectorCffi::RelationSet(value_vec), SafetyCheckId::Vector)
728                     .into_ptr() as *const OhCloudExtVector;
729         }
730         HashMapCffi::AppInfo(map) => {
731             let key_vec: Vec<String> = map.keys().cloned().collect();
732             let mut value_vec = vec![];
733             for src in map.values() {
734                 value_vec.push(src.clone());
735             }
736 
737             *key = OhCloudExtVector::new(VectorCffi::String(key_vec), SafetyCheckId::Vector)
738                 .into_ptr() as *const OhCloudExtVector;
739             *value = OhCloudExtVector::new(VectorCffi::AppInfo(value_vec), SafetyCheckId::Vector)
740                 .into_ptr() as *const OhCloudExtVector;
741         }
742         HashMapCffi::VecU32(map) => {
743             let key_vec: Vec<String> = map.keys().cloned().collect();
744             let value_vec: Vec<Vec<u32>> = map.values().cloned().collect();
745 
746             *key = OhCloudExtVector::new(VectorCffi::String(key_vec), SafetyCheckId::Vector)
747                 .into_ptr() as *const OhCloudExtVector;
748             *value = OhCloudExtVector::new(VectorCffi::VecU32(value_vec), SafetyCheckId::Vector)
749                 .into_ptr() as *const OhCloudExtVector;
750         }
751         HashMapCffi::VecString(map) => {
752             let key_vec: Vec<String> = map.keys().cloned().collect();
753             let value_vec: Vec<Vec<String>> = map.values().cloned().collect();
754 
755             *key = OhCloudExtVector::new(VectorCffi::String(key_vec), SafetyCheckId::Vector)
756                 .into_ptr() as *const OhCloudExtVector;
757             *value = OhCloudExtVector::new(VectorCffi::VecString(value_vec), SafetyCheckId::Vector)
758                 .into_ptr() as *const OhCloudExtVector;
759         }
760         HashMapCffi::VecDatabase(map) => {
761             let key_vec: Vec<String> = map.keys().cloned().collect();
762             let mut value_vec = vec![];
763             for src in map.values() {
764                 value_vec.push(src.clone());
765             }
766             *key = OhCloudExtVector::new(VectorCffi::String(key_vec), SafetyCheckId::Vector)
767                 .into_ptr() as *const OhCloudExtVector;
768             *value =
769                 OhCloudExtVector::new(VectorCffi::VecDatabase(value_vec), SafetyCheckId::Vector)
770                     .into_ptr() as *const OhCloudExtVector;
771         }
772     }
773     ERRNO_SUCCESS
774 }
775 
776 /// According to key, get value from the Hashmap pointer. If returning type is not raw C type
777 /// pointer, these pointers should be freed by corresponding free functions.
778 ///
779 /// # Safety
780 /// Pointer passed in should be valid during the whole lifetime of this function, or memory issues
781 /// might happen. Besides, pointers should also be interpreted as same as the types used in
782 /// initialization of the Vector.
783 #[no_mangle]
OhCloudExtHashMapGet( hash_map: *const OhCloudExtHashMap, key: *const c_uchar, key_len: c_uint, value: *mut *const c_void, value_len: *mut c_uint, ) -> c_int784 pub unsafe extern "C" fn OhCloudExtHashMapGet(
785     hash_map: *const OhCloudExtHashMap,
786     key: *const c_uchar,
787     key_len: c_uint,
788     value: *mut *const c_void,
789     value_len: *mut c_uint,
790 ) -> c_int {
791     if hash_map.is_null() || key.is_null() || value.is_null() || value_len.is_null() {
792         return ERRNO_NULLPTR;
793     }
794     let hash_map = match OhCloudExtHashMap::get_inner_ref(hash_map, SafetyCheckId::HashMap) {
795         None => return ERRNO_WRONG_TYPE,
796         Some(v) => v,
797     };
798     let key_bytes = &*slice_from_raw_parts(key, key_len as usize);
799     let key = std::str::from_utf8_unchecked(key_bytes);
800     match hash_map {
801         HashMapCffi::U32(map) => {
802             if let Some(val) = map.get(key) {
803                 *value = val as *const _ as *const c_void;
804             }
805         }
806         HashMapCffi::String(map) => {
807             if let Some(val) = map.get(key) {
808                 *value = val.as_ptr() as *const c_void;
809                 *value_len = val.len() as c_uint;
810             }
811         }
812         HashMapCffi::Value(map) => {
813             if let Some(val) = map.get(key) {
814                 *value = OhCloudExtValue::new(val.clone(), SafetyCheckId::Value).into_ptr()
815                     as *const c_void;
816             }
817         }
818         HashMapCffi::Table(map) => {
819             if let Some(val) = map.get(key) {
820                 *value = OhCloudExtTable::new(val.clone(), SafetyCheckId::Table).into_ptr()
821                     as *const c_void;
822             }
823         }
824         HashMapCffi::RelationSet(map) => {
825             if let Some(val) = map.get(key) {
826                 *value = OhCloudExtRelationSet::new(val.clone(), SafetyCheckId::RelationSet)
827                     .into_ptr() as *const c_void;
828             }
829         }
830         HashMapCffi::AppInfo(map) => {
831             if let Some(val) = map.get(key) {
832                 *value = OhCloudExtAppInfo::new(val.clone(), SafetyCheckId::AppInfo).into_ptr()
833                     as *const c_void;
834             }
835         }
836         HashMapCffi::VecU32(map) => {
837             if let Some(val) = map.get(key) {
838                 *value = OhCloudExtVector::new(VectorCffi::U32(val.clone()), SafetyCheckId::Vector)
839                     .into_ptr() as *const c_void;
840             }
841         }
842         HashMapCffi::VecString(map) => {
843             if let Some(val) = map.get(key) {
844                 *value =
845                     OhCloudExtVector::new(VectorCffi::String(val.clone()), SafetyCheckId::Vector)
846                         .into_ptr() as *const c_void;
847             }
848         }
849         HashMapCffi::VecDatabase(map) => {
850             if let Some(val) = map.get(key) {
851                 *value =
852                     OhCloudExtVector::new(VectorCffi::Database(val.clone()), SafetyCheckId::Vector)
853                         .into_ptr() as *const c_void;
854             }
855         }
856     }
857     ERRNO_SUCCESS
858 }
859 
860 /// Free a Hashmap pointer.
861 ///
862 /// # Safety
863 /// Pointer passed in should be valid during the whole lifetime of this function, or memory issues
864 /// might happen.
865 #[no_mangle]
OhCloudExtHashMapFree(hash_map: *mut OhCloudExtHashMap)866 pub unsafe extern "C" fn OhCloudExtHashMapFree(hash_map: *mut OhCloudExtHashMap) {
867     let _ = OhCloudExtHashMap::from_ptr(hash_map, SafetyCheckId::HashMap);
868 }
869 
870 #[cfg(test)]
871 mod test {
872     use crate::c_adapter::basic_rust_types::*;
873     use crate::c_adapter::cloud_ext_types::{OhCloudExtValueNew, OhCloudExtValueType};
874     use crate::service_impl;
875     use std::ptr::null;
876 
877     macro_rules! ut_vec {
878         (
879             $typ: ident,
880             $push: ident,
881             $value_typ: ty,
882             $value: ident
883         ) => {
884             let typ = OhCloudExtRustType::$typ;
885             let new_vec = OhCloudExtVectorNew(typ);
886             assert!(!new_vec.is_null());
887             match OhCloudExtVectorGetValueTyp(new_vec) {
888                 OhCloudExtRustType::$typ => {}
889                 _ => panic!("Vector Type wrong"),
890             }
891 
892             let mut length: u32 = 1;
893             assert_eq!(
894                 OhCloudExtVectorGetLength(new_vec, &mut length as *mut _ as *mut c_uint),
895                 ERRNO_SUCCESS
896             );
897             assert_eq!(length, 0);
898 
899             assert_eq!(
900                 // Length of test string "hello"
901                 OhCloudExtVectorPush(new_vec, $push as *const _ as *mut c_void, 5),
902                 ERRNO_SUCCESS
903             );
904             assert_eq!(
905                 OhCloudExtVectorGetLength(new_vec, &mut length as *mut _ as *mut c_uint),
906                 ERRNO_SUCCESS
907             );
908             assert_eq!(length, 1);
909 
910             let mut val = null();
911             assert_eq!(
912                 OhCloudExtVectorGet(
913                     new_vec,
914                     0,
915                     &mut val as *mut _ as *mut *const c_void,
916                     &mut length as *mut _ as *mut c_uint
917                 ),
918                 ERRNO_SUCCESS
919             );
920             let typ = OhCloudExtRustType::$typ;
921             match typ {
922                 OhCloudExtRustType::VEC_U32 => {
923                     let value_struct = OhCloudExtVector::get_inner(
924                         val as *mut OhCloudExtVector,
925                         SafetyCheckId::Vector,
926                     )
927                     .unwrap();
928                     match value_struct {
929                         // ut_vec_vecu32
930                         VectorCffi::U32(v) => assert_eq!(*v, vec![3_u32]),
931                         _ => panic!("Vector type mismatches with VecU32."),
932                     }
933                 }
934                 OhCloudExtRustType::STRING => {
935                     let slice = &(*slice_from_raw_parts(val as *const u8, length as usize));
936                     assert_eq!(slice, b"hello");
937                 }
938                 OhCloudExtRustType::VALUE => {
939                     let v = OhCloudExtValue::get_inner(
940                         val as *mut OhCloudExtValue,
941                         SafetyCheckId::Value,
942                     )
943                     .unwrap();
944                     assert_eq!(v, service_impl::types::Value::Empty);
945                 }
946                 _ => {
947                     let value = &*(val as *const $value_typ);
948                     assert_eq!(value, &$value);
949                 }
950             }
951             OhCloudExtVectorFree(new_vec);
952         };
953     }
954 
955     /// UT test for Vec<i32> creation and destruction.
956     ///
957     /// # Title
958     /// ut_vec_i32
959     ///
960     /// # Brief
961     /// 1. Create a vec of i32.
962     /// 2. Push and get values from it.
963     /// 3. Free vec.
964     /// 4. No error and memory leak should happen.
965     #[test]
ut_vec_i32()966     fn ut_vec_i32() {
967         unsafe {
968             let src: i32 = 3;
969             let borrow = &src;
970             ut_vec!(I32, borrow, i32, src);
971         }
972     }
973 
974     /// UT test for Vec<u32> creation and destruction.
975     ///
976     /// # Title
977     /// ut_vec_u32
978     ///
979     /// # Brief
980     /// 1. Create a vec of u32.
981     /// 2. Push and get values from it.
982     /// 3. Free vec.
983     /// 4. No error and memory leak should happen.
984     #[test]
ut_vec_u32()985     fn ut_vec_u32() {
986         unsafe {
987             let src: u32 = 3;
988             let borrow = &src;
989             ut_vec!(U32, borrow, u32, src);
990         }
991     }
992 
993     /// UT test for Vec<String> creation and destruction.
994     ///
995     /// # Title
996     /// ut_vec_string
997     ///
998     /// # Brief
999     /// 1. Create a vec of string.
1000     /// 2. Push and get values from it.
1001     /// 3. Free vec.
1002     /// 4. No error and memory leak should happen.
1003     #[test]
ut_vec_string()1004     fn ut_vec_string() {
1005         unsafe {
1006             let src = "hello".to_string();
1007             let borrow = src.as_ptr();
1008             ut_vec!(STRING, borrow, String, src);
1009         }
1010     }
1011 
1012     /// UT test for Vec<Value> creation and destruction.
1013     ///
1014     /// # Title
1015     /// ut_vec_u32
1016     ///
1017     /// # Brief
1018     /// 1. Create a vec of Value.
1019     /// 2. Push and get values from it.
1020     /// 3. Free vec.
1021     /// 4. No error and memory leak should happen.
1022     #[test]
ut_vec_value()1023     fn ut_vec_value() {
1024         unsafe {
1025             let src = OhCloudExtValueNew(OhCloudExtValueType::EMPTY, null_mut(), 0);
1026             let cmp = types::Value::Empty;
1027             assert!(!src.is_null());
1028             ut_vec!(VALUE, src, types::Value, cmp);
1029         }
1030     }
1031 
1032     /// UT test for Vec<Vec<u32>> creation and destruction.
1033     ///
1034     /// # Title
1035     /// ut_vec_vecu32
1036     ///
1037     /// # Brief
1038     /// 1. Create a vec of Vec<u32>.
1039     /// 2. Push and get values from it.
1040     /// 3. Free vec.
1041     /// 4. No error and memory leak should happen.
1042     #[test]
ut_vec_vecu32()1043     fn ut_vec_vecu32() {
1044         unsafe {
1045             let vec = OhCloudExtVectorNew(OhCloudExtRustType::U32);
1046             let mut src: u32 = 3;
1047             assert_eq!(
1048                 OhCloudExtVectorPush(vec, &mut src as *mut _ as *mut c_void, 1),
1049                 ERRNO_SUCCESS
1050             );
1051 
1052             let src = vec![3_u32];
1053             ut_vec!(VEC_U32, vec, Vec<u32>, src);
1054         }
1055     }
1056 
1057     /// UT test for vec use and create.
1058     ///
1059     /// # Title
1060     /// ut_vec_null
1061     ///
1062     /// # Brief
1063     /// 1. Pass in null ptr into vec cffi func.
1064     /// 2. No error and memory leak should happen.
1065     #[test]
ut_vec_null()1066     fn ut_vec_null() {
1067         unsafe {
1068             let mut src = 3;
1069             assert!(OhCloudExtVectorNew(OhCloudExtRustType::NULL).is_null());
1070             assert_eq!(
1071                 OhCloudExtVectorPush(null_mut(), &mut src as *mut _ as *mut c_void, 0),
1072                 ERRNO_NULLPTR
1073             );
1074 
1075             let typ = OhCloudExtRustType::I32;
1076             let new_vec = OhCloudExtVectorNew(typ);
1077             let mut length = 1;
1078             assert_eq!(
1079                 OhCloudExtVectorGetLength(null_mut(), &mut length as *mut _ as *mut c_uint),
1080                 ERRNO_NULLPTR
1081             );
1082             assert_eq!(OhCloudExtVectorPush(new_vec, null_mut(), 0), ERRNO_NULLPTR);
1083             OhCloudExtVectorFree(new_vec);
1084         }
1085     }
1086 
1087     macro_rules! ut_hashmap {
1088         (
1089             $typ: ident,
1090             $push: ident,
1091             $value_typ: ty,
1092             $value: ident
1093         ) => {
1094             let typ = OhCloudExtRustType::$typ;
1095             let new_map = OhCloudExtHashMapNew(typ);
1096             assert!(!new_map.is_null());
1097             match OhCloudExtHashMapGetKeyTyp(new_map) {
1098                 OhCloudExtRustType::STRING => {}
1099                 _ => panic!("Hashmap key type wrong"),
1100             }
1101             match OhCloudExtHashMapGetValueTyp(new_map) {
1102                 OhCloudExtRustType::$typ => {}
1103                 _ => panic!("Hashmap value wrong"),
1104             }
1105 
1106             let mut length = 1;
1107             assert_eq!(
1108                 OhCloudExtHashMapGetLength(new_map, &mut length as *mut _ as *mut c_uint),
1109                 ERRNO_SUCCESS
1110             );
1111             assert_eq!(length, 0);
1112 
1113             let key = "key";
1114             assert_eq!(
1115                 OhCloudExtHashMapInsert(
1116                     new_map,
1117                     key.as_ptr() as *mut c_uchar,
1118                     key.len() as c_uint,
1119                     $push as *const _ as *mut c_void,
1120                     0
1121                 ),
1122                 ERRNO_SUCCESS
1123             );
1124             assert_eq!(
1125                 OhCloudExtHashMapGetLength(new_map, &mut length as *mut _ as *mut c_uint),
1126                 ERRNO_SUCCESS
1127             );
1128             assert_eq!(length, 1);
1129 
1130             let mut key_ptr: *mut OhCloudExtVector = null_mut();
1131             let mut value_ptr: *mut OhCloudExtVector = null_mut();
1132             assert_eq!(
1133                 OhCloudExtHashMapIterGetKeyValuePair(
1134                     new_map,
1135                     (&mut key_ptr) as *mut _ as *mut *const OhCloudExtVector,
1136                     (&mut value_ptr) as *mut _ as *mut *const OhCloudExtVector,
1137                 ),
1138                 ERRNO_SUCCESS
1139             );
1140             assert!(!key_ptr.is_null());
1141             assert!(!value_ptr.is_null());
1142 
1143             let mut val = null();
1144             assert_eq!(
1145                 OhCloudExtVectorGet(
1146                     key_ptr,
1147                     0,
1148                     &mut val as *mut _ as *mut *const c_void,
1149                     &mut length as *mut _ as *mut c_uint
1150                 ),
1151                 ERRNO_SUCCESS
1152             );
1153 
1154             let key_slice = &*slice_from_raw_parts(val as *const u8, length);
1155             assert_eq!(key_slice, b"key");
1156             OhCloudExtVectorFree(key_ptr);
1157 
1158             assert_eq!(
1159                 OhCloudExtVectorGet(
1160                     value_ptr,
1161                     0,
1162                     &mut val as *mut _ as *mut *const c_void,
1163                     &mut length as *mut _ as *mut c_uint
1164                 ),
1165                 ERRNO_SUCCESS
1166             );
1167             match OhCloudExtVectorGetValueTyp(value_ptr) {
1168                 OhCloudExtRustType::VEC_U32 => {
1169                     let value_struct = OhCloudExtVector::get_inner(
1170                         val as *mut OhCloudExtVector,
1171                         SafetyCheckId::Vector,
1172                     )
1173                     .unwrap();
1174                     match value_struct {
1175                         // ut_vec_vecu32
1176                         VectorCffi::U32(v) => assert_eq!(*v, vec![3]),
1177                         _ => panic!("Vector type mismatches with VecU32."),
1178                     }
1179                 }
1180                 _ => {
1181                     let value = &*(val as *const $value_typ);
1182                     assert_eq!(value, $value);
1183                 }
1184             }
1185             OhCloudExtVectorFree(value_ptr);
1186 
1187             let mut val = null();
1188             let mut length = 1;
1189             assert_eq!(
1190                 OhCloudExtHashMapGet(
1191                     new_map,
1192                     key.as_ptr() as *const c_uchar,
1193                     key.len() as c_uint,
1194                     &mut val as *mut _ as *mut *const c_void,
1195                     &mut length as *mut _ as *mut c_uint
1196                 ),
1197                 ERRNO_SUCCESS
1198             );
1199             match OhCloudExtHashMapGetValueTyp(new_map) {
1200                 OhCloudExtRustType::VEC_U32 => {
1201                     let value_struct = OhCloudExtVector::get_inner(
1202                         val as *mut OhCloudExtVector,
1203                         SafetyCheckId::Vector,
1204                     )
1205                     .unwrap();
1206                     match value_struct {
1207                         // ut_hashmap_vecu32
1208                         VectorCffi::U32(v) => assert_eq!(*v, vec![3_u32]),
1209                         _ => panic!("Vector type mismatches with VecU32."),
1210                     }
1211                 }
1212                 _ => {
1213                     let value = &*(val as *const $value_typ);
1214                     assert_eq!(value, $value);
1215                 }
1216             }
1217 
1218             OhCloudExtHashMapFree(new_map);
1219         };
1220     }
1221 
1222     /// UT test for hashmap use and create.
1223     ///
1224     /// # Title
1225     /// ut_hashmap_u32
1226     ///
1227     /// # Brief
1228     /// 1. Create a HashMap<String, u32>.
1229     /// 2. Push and get values from it.
1230     /// 3. Free vec.
1231     /// 4. No error and memory leak should happen.
1232     #[test]
ut_hashmap_u32()1233     fn ut_hashmap_u32() {
1234         unsafe {
1235             let src: u32 = 3;
1236             let borrow = &src;
1237             ut_hashmap!(U32, borrow, u32, borrow);
1238         }
1239     }
1240 
1241     /// UT test for hashmap use and create.
1242     ///
1243     /// # Title
1244     /// ut_hashmap_u32
1245     ///
1246     /// # Brief
1247     /// 1. Create a HashMap<String, Vec<u32>>.
1248     /// 2. Push and get values from it.
1249     /// 3. Free vec.
1250     /// 4. No error and memory leak should happen.
1251     #[test]
ut_hashmap_vecu32()1252     fn ut_hashmap_vecu32() {
1253         unsafe {
1254             let vec = OhCloudExtVectorNew(OhCloudExtRustType::U32);
1255             let mut src: u32 = 3;
1256             assert_eq!(
1257                 OhCloudExtVectorPush(vec, &mut src as *mut _ as *mut c_void, 1),
1258                 ERRNO_SUCCESS
1259             );
1260 
1261             let src = vec![3_u32];
1262             let borrow = &src;
1263             ut_hashmap!(VEC_U32, vec, Vec<u32>, borrow);
1264         }
1265     }
1266 
1267     /// UT test for hashmap use and create.
1268     ///
1269     /// # Title
1270     /// ut_hashmap_null
1271     ///
1272     /// # Brief
1273     /// 1. Pass in null ptr into hashmap cffi func.
1274     /// 2. No error and memory leak should happen.
1275     #[test]
ut_hashmap_null()1276     fn ut_hashmap_null() {
1277         unsafe {
1278             assert!(OhCloudExtHashMapNew(OhCloudExtRustType::NULL).is_null());
1279             let typ = OhCloudExtHashMapGetKeyTyp(null_mut());
1280             match typ {
1281                 OhCloudExtRustType::NULL => {}
1282                 _ => panic!("Get value type from null ptr is not ValueType::NULL"),
1283             }
1284             let typ = OhCloudExtHashMapGetValueTyp(null_mut());
1285             match typ {
1286                 OhCloudExtRustType::NULL => {}
1287                 _ => panic!("Get value type from null ptr is not ValueType::NULL"),
1288             }
1289 
1290             let typ = OhCloudExtRustType::U32;
1291             let new_map = OhCloudExtHashMapNew(typ);
1292             let mut length = 0;
1293             assert!(!new_map.is_null());
1294             let mut src = 3_u8;
1295             assert_eq!(
1296                 OhCloudExtHashMapInsert(
1297                     null_mut(),
1298                     "key".as_ptr() as *mut c_uchar,
1299                     3,
1300                     &mut src as *mut _ as *mut c_void,
1301                     0
1302                 ),
1303                 ERRNO_NULLPTR
1304             );
1305             assert_eq!(
1306                 OhCloudExtHashMapGetLength(null_mut(), &mut length as *mut _ as *mut c_uint),
1307                 ERRNO_NULLPTR
1308             );
1309             OhCloudExtHashMapFree(new_map);
1310         }
1311     }
1312 }
1313