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