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::basic_rust_types::{HashMapCffi, VectorCffi};
17 use crate::c_adapter::*;
18 use crate::ipc_conn;
19 use crate::service_impl::{asset_loader, cloud_db, cloud_service, types};
20 use std::collections::HashMap;
21 use std::ffi::{c_int, c_longlong, c_uchar, c_uint, c_ulonglong, c_void};
22 use std::ptr::{null, null_mut, slice_from_raw_parts};
23 
24 /// CloudAssetBuilder defined in C struct. It will be used to build a Rust CloudAsset struct in use.
25 #[repr(C)]
26 pub struct OhCloudExtCloudAssetBuilder {
27     pub version: u64,
28     pub status: asset_loader::AssetStatus,
29     pub expires_time: u64,
30     pub id: *const c_uchar,
31     pub id_len: c_uint,
32     pub name: *const c_uchar,
33     pub name_len: c_uint,
34     pub uri: *const c_uchar,
35     pub uri_len: c_uint,
36     pub local_path: *const c_uchar,
37     pub local_path_len: c_uint,
38     pub create_time: *const c_uchar,
39     pub create_time_len: c_uint,
40     pub modify_time: *const c_uchar,
41     pub modify_time_len: c_uint,
42     pub size: *const c_uchar,
43     pub size_len: c_uint,
44     pub hash: *const c_uchar,
45     pub hash_len: c_uint,
46 }
47 
48 /// Enumeration represents inner type of contents in Value enum.
49 #[repr(C)]
50 #[allow(non_camel_case_types, clippy::upper_case_acronyms)]
51 #[derive(Debug, Eq, PartialEq)]
52 pub enum OhCloudExtValueType {
53     EMPTY = 0,
54     INT,
55     FLOAT,
56     STRING,
57     BOOL,
58     BYTES,
59     ASSET,
60     ASSETS,
61 }
62 
63 /// Value pointer passed to C side.
64 pub type OhCloudExtValue = SafeCffiWrapper<types::Value>;
65 /// CloudAsset pointer passed to C side.
66 pub type OhCloudExtCloudAsset = SafeCffiWrapper<ipc_conn::CloudAsset>;
67 /// Database pointer passed to C side.
68 pub type OhCloudExtDatabase = SafeCffiWrapper<types::Database>;
69 /// CloudInfo pointer passed to C side.
70 pub type OhCloudExtCloudInfo = SafeCffiWrapper<cloud_service::CloudInfo>;
71 /// AppInfo pointer passed to C side.
72 pub type OhCloudExtAppInfo = SafeCffiWrapper<cloud_service::AppInfo>;
73 /// Table pointer passed to C side.
74 pub type OhCloudExtTable = SafeCffiWrapper<types::Table>;
75 /// Field pointer passed to C side.
76 pub type OhCloudExtField = SafeCffiWrapper<types::Field>;
77 /// SchemaMeta pointer passed to C side.
78 pub type OhCloudExtSchemaMeta = SafeCffiWrapper<cloud_service::SchemaMeta>;
79 /// RelationSet pointer passed to C side.
80 pub type OhCloudExtRelationSet = SafeCffiWrapper<cloud_service::RelationSet>;
81 /// CloudDbData pointer passed to C side.
82 pub type OhCloudExtCloudDbData = SafeCffiWrapper<cloud_db::CloudDbData>;
83 /// ValueBucket pointer passed to C side.
84 pub type OhCloudExtValueBucket = SafeCffiWrapper<ipc_conn::ValueBucket>;
85 
86 /// Create a Value instance according to ValueInnerType.
87 #[no_mangle]
OhCloudExtValueNew( typ: OhCloudExtValueType, content: *mut c_void, len: c_uint, ) -> *mut OhCloudExtValue88 pub unsafe extern "C" fn OhCloudExtValueNew(
89     typ: OhCloudExtValueType,
90     content: *mut c_void,
91     len: c_uint,
92 ) -> *mut OhCloudExtValue {
93     if typ != OhCloudExtValueType::EMPTY && content.is_null() {
94         return null_mut();
95     }
96 
97     let val = match typ {
98         OhCloudExtValueType::EMPTY => types::Value::Empty,
99         OhCloudExtValueType::INT => {
100             let int = &*(content as *mut i64);
101             types::Value::Int(*int)
102         }
103         OhCloudExtValueType::FLOAT => {
104             let float = &*(content as *mut f64);
105             types::Value::Float(*float)
106         }
107         OhCloudExtValueType::BOOL => {
108             let bool = &*(content as *mut u8);
109             types::Value::Bool(c_bool_to_bool(*bool))
110         }
111         OhCloudExtValueType::STRING => {
112             let str = char_ptr_to_string(content as *const c_uchar, len);
113             types::Value::String(str)
114         }
115         OhCloudExtValueType::BYTES => {
116             let slice = &(*slice_from_raw_parts(content as *const u8, len as usize));
117             types::Value::Bytes(slice.to_vec())
118         }
119         OhCloudExtValueType::ASSET => {
120             let asset = match OhCloudExtCloudAsset::get_inner(
121                 content as *mut OhCloudExtCloudAsset,
122                 SafetyCheckId::CloudAsset,
123             ) {
124                 None => return null_mut(),
125                 Some(v) => v,
126             };
127             types::Value::Asset(asset)
128         }
129         OhCloudExtValueType::ASSETS => {
130             let assets = match OhCloudExtVector::get_inner(
131                 content as *mut OhCloudExtVector,
132                 SafetyCheckId::Vector,
133             ) {
134                 None => return null_mut(),
135                 Some(v) => v,
136             };
137             match assets {
138                 VectorCffi::CloudAsset(v) => types::Value::Assets(v),
139                 _ => return null_mut(),
140             }
141         }
142     };
143 
144     OhCloudExtValue::new(val, SafetyCheckId::Value).into_ptr() as *mut OhCloudExtValue
145 }
146 
147 /// Get content from a Value pointer.
148 ///
149 /// If the Value is Value::Assets or Value::Asset, the Vector pointer returned should be freed by
150 /// `VectorFree`.
151 #[no_mangle]
OhCloudExtValueGetContent( src: *mut OhCloudExtValue, typ: *mut OhCloudExtValueType, content: *mut *const c_void, len: *mut c_uint, ) -> c_int152 pub unsafe extern "C" fn OhCloudExtValueGetContent(
153     src: *mut OhCloudExtValue,
154     typ: *mut OhCloudExtValueType,
155     content: *mut *const c_void,
156     len: *mut c_uint,
157 ) -> c_int {
158     if src.is_null() || typ.is_null() || content.is_null() || len.is_null() {
159         return ERRNO_NULLPTR;
160     }
161 
162     let value_struct = match OhCloudExtValue::get_inner_ref(src, SafetyCheckId::Value) {
163         None => return ERRNO_WRONG_TYPE,
164         Some(v) => v,
165     };
166     match value_struct {
167         types::Value::Empty => {
168             *typ = OhCloudExtValueType::EMPTY;
169             *content = null();
170             *len = 0;
171         }
172         types::Value::Int(c) => {
173             *typ = OhCloudExtValueType::INT;
174             *content = c as *const _ as *const c_void;
175         }
176         types::Value::Float(c) => {
177             *typ = OhCloudExtValueType::FLOAT;
178             *content = c as *const _ as *const c_void;
179         }
180         types::Value::String(c) => {
181             *typ = OhCloudExtValueType::STRING;
182             *content = c.as_ptr() as *const c_void;
183             *len = c.len() as c_uint;
184         }
185         types::Value::Bool(c) => {
186             *typ = OhCloudExtValueType::BOOL;
187             *content = c as *const _ as *const c_void;
188         }
189         types::Value::Bytes(c) => {
190             *typ = OhCloudExtValueType::BYTES;
191             *content = c.as_ptr() as *const c_void;
192             *len = c.len() as c_uint;
193         }
194         types::Value::Asset(c) => {
195             *typ = OhCloudExtValueType::ASSET;
196             *content = OhCloudExtCloudAsset::new(c.clone(), SafetyCheckId::CloudAsset).into_ptr()
197                 as *mut c_void;
198         }
199         types::Value::Assets(c) => {
200             *typ = OhCloudExtValueType::ASSETS;
201             let vec = VectorCffi::CloudAsset(c.to_vec());
202             *content = OhCloudExtVector::new(vec, SafetyCheckId::Vector).into_ptr() as *mut c_void;
203             *len = c.len() as c_uint;
204         }
205     }
206     ERRNO_SUCCESS
207 }
208 
209 /// Free a Value pointer.
210 #[no_mangle]
OhCloudExtValueFree(src: *mut OhCloudExtValue)211 pub unsafe extern "C" fn OhCloudExtValueFree(src: *mut OhCloudExtValue) {
212     let _ = OhCloudExtValue::from_ptr(src, SafetyCheckId::Value);
213 }
214 
get_cloud_asset(builder: *const OhCloudExtCloudAssetBuilder) -> ipc_conn::CloudAsset215 unsafe fn get_cloud_asset(builder: *const OhCloudExtCloudAssetBuilder) -> ipc_conn::CloudAsset {
216     let builder = &*builder;
217     let id = char_ptr_to_string(builder.id, builder.id_len);
218     let name = char_ptr_to_string(builder.name, builder.name_len);
219     let uri = char_ptr_to_string(builder.uri, builder.uri_len);
220     let local_path = char_ptr_to_string(builder.local_path, builder.local_path_len);
221     let create_time = char_ptr_to_string(builder.create_time, builder.create_time_len);
222     let modify_time = char_ptr_to_string(builder.modify_time, builder.modify_time_len);
223     let size = char_ptr_to_string(builder.size, builder.size_len);
224     let hash = char_ptr_to_string(builder.hash, builder.hash_len);
225     ipc_conn::CloudAsset {
226         asset_id: id,
227         status: builder.status.clone(),
228         asset_name: name,
229         hash,
230         uri,
231         sub_path: local_path,
232         create_time,
233         modify_time,
234         size,
235     }
236 }
237 
238 /// Initialize an CloudAsset by the CloudAssetBuilder.
239 #[no_mangle]
OhCloudExtCloudAssetNew( builder: *const OhCloudExtCloudAssetBuilder, ) -> *mut OhCloudExtCloudAsset240 pub unsafe extern "C" fn OhCloudExtCloudAssetNew(
241     builder: *const OhCloudExtCloudAssetBuilder,
242 ) -> *mut OhCloudExtCloudAsset {
243     if builder.is_null() {
244         return null_mut();
245     }
246 
247     let cloud_asset = get_cloud_asset(builder);
248     OhCloudExtCloudAsset::new(cloud_asset, SafetyCheckId::CloudAsset).into_ptr()
249         as *mut OhCloudExtCloudAsset
250 }
251 
252 /// Get id from an CloudAsset pointer.
253 #[no_mangle]
OhCloudExtCloudAssetGetId( src: *const OhCloudExtCloudAsset, id: *mut *const c_uchar, len: *mut c_uint, ) -> c_int254 pub unsafe extern "C" fn OhCloudExtCloudAssetGetId(
255     src: *const OhCloudExtCloudAsset,
256     id: *mut *const c_uchar,
257     len: *mut c_uint,
258 ) -> c_int {
259     if src.is_null() || id.is_null() || len.is_null() {
260         return ERRNO_NULLPTR;
261     }
262 
263     let src_struct = match OhCloudExtCloudAsset::get_inner_ref(src, SafetyCheckId::CloudAsset) {
264         None => return ERRNO_WRONG_TYPE,
265         Some(v) => v,
266     };
267     *id = src_struct.id().as_ptr() as *const c_uchar;
268     *len = src_struct.id().len() as c_uint;
269     ERRNO_SUCCESS
270 }
271 
272 /// Get name from an CloudAsset pointer.
273 #[no_mangle]
OhCloudExtCloudAssetGetName( src: *const OhCloudExtCloudAsset, name: *mut *const c_uchar, len: *mut c_uint, ) -> c_int274 pub unsafe extern "C" fn OhCloudExtCloudAssetGetName(
275     src: *const OhCloudExtCloudAsset,
276     name: *mut *const c_uchar,
277     len: *mut c_uint,
278 ) -> c_int {
279     if src.is_null() || name.is_null() || len.is_null() {
280         return ERRNO_NULLPTR;
281     }
282 
283     let src_struct = match OhCloudExtCloudAsset::get_inner_ref(src, SafetyCheckId::CloudAsset) {
284         None => return ERRNO_WRONG_TYPE,
285         Some(v) => v,
286     };
287     *name = src_struct.name().as_ptr() as *const c_uchar;
288     *len = src_struct.name().len() as c_uint;
289     ERRNO_SUCCESS
290 }
291 
292 /// Get uri from an CloudAsset pointer.
293 #[no_mangle]
OhCloudExtCloudAssetGetUri( src: *const OhCloudExtCloudAsset, uri: *mut *const c_uchar, len: *mut c_uint, ) -> c_int294 pub unsafe extern "C" fn OhCloudExtCloudAssetGetUri(
295     src: *const OhCloudExtCloudAsset,
296     uri: *mut *const c_uchar,
297     len: *mut c_uint,
298 ) -> c_int {
299     if src.is_null() || uri.is_null() || len.is_null() {
300         return ERRNO_NULLPTR;
301     }
302 
303     let src_struct = match OhCloudExtCloudAsset::get_inner_ref(src, SafetyCheckId::CloudAsset) {
304         None => return ERRNO_WRONG_TYPE,
305         Some(v) => v,
306     };
307     *uri = src_struct.uri().as_ptr() as *const c_uchar;
308     *len = src_struct.uri().len() as c_uint;
309     ERRNO_SUCCESS
310 }
311 
312 /// Get local path from an CloudAsset pointer.
313 #[no_mangle]
OhCloudExtCloudAssetGetLocalPath( src: *const OhCloudExtCloudAsset, local_path: *mut *const c_uchar, len: *mut c_uint, ) -> c_int314 pub unsafe extern "C" fn OhCloudExtCloudAssetGetLocalPath(
315     src: *const OhCloudExtCloudAsset,
316     local_path: *mut *const c_uchar,
317     len: *mut c_uint,
318 ) -> c_int {
319     if src.is_null() || local_path.is_null() || len.is_null() {
320         return ERRNO_NULLPTR;
321     }
322 
323     let src_struct = match OhCloudExtCloudAsset::get_inner_ref(src, SafetyCheckId::CloudAsset) {
324         None => return ERRNO_WRONG_TYPE,
325         Some(v) => v,
326     };
327     *local_path = src_struct.local_path().as_ptr() as *const c_uchar;
328     *len = src_struct.local_path().len() as c_uint;
329     ERRNO_SUCCESS
330 }
331 
332 /// Get create time from an CloudAsset pointer.
333 #[no_mangle]
OhCloudExtCloudAssetGetCreateTime( src: *const OhCloudExtCloudAsset, create_time: *mut *const c_uchar, len: *mut c_uint, ) -> c_int334 pub unsafe extern "C" fn OhCloudExtCloudAssetGetCreateTime(
335     src: *const OhCloudExtCloudAsset,
336     create_time: *mut *const c_uchar,
337     len: *mut c_uint,
338 ) -> c_int {
339     if src.is_null() || create_time.is_null() || len.is_null() {
340         return ERRNO_NULLPTR;
341     }
342 
343     let src_struct = match OhCloudExtCloudAsset::get_inner_ref(src, SafetyCheckId::CloudAsset) {
344         None => return ERRNO_WRONG_TYPE,
345         Some(v) => v,
346     };
347     *create_time = src_struct.create_time().as_ptr() as *const c_uchar;
348     *len = src_struct.create_time().len() as c_uint;
349     ERRNO_SUCCESS
350 }
351 
352 /// Get modified time from an CloudAsset pointer.
353 #[no_mangle]
OhCloudExtCloudAssetGetModifiedTime( src: *const OhCloudExtCloudAsset, modify_time: *mut *const c_uchar, len: *mut c_uint, ) -> c_int354 pub unsafe extern "C" fn OhCloudExtCloudAssetGetModifiedTime(
355     src: *const OhCloudExtCloudAsset,
356     modify_time: *mut *const c_uchar,
357     len: *mut c_uint,
358 ) -> c_int {
359     if src.is_null() || modify_time.is_null() || len.is_null() {
360         return ERRNO_NULLPTR;
361     }
362 
363     let src_struct = match OhCloudExtCloudAsset::get_inner_ref(src, SafetyCheckId::CloudAsset) {
364         None => return ERRNO_WRONG_TYPE,
365         Some(v) => v,
366     };
367     *modify_time = src_struct.modify_time().as_ptr() as *const c_uchar;
368     *len = src_struct.modify_time().len() as c_uint;
369     ERRNO_SUCCESS
370 }
371 
372 /// Get size from an CloudAsset pointer.
373 #[no_mangle]
OhCloudExtCloudAssetGetSize( src: *const OhCloudExtCloudAsset, size: *mut *const c_uchar, len: *mut c_uint, ) -> c_int374 pub unsafe extern "C" fn OhCloudExtCloudAssetGetSize(
375     src: *const OhCloudExtCloudAsset,
376     size: *mut *const c_uchar,
377     len: *mut c_uint,
378 ) -> c_int {
379     if src.is_null() || size.is_null() || len.is_null() {
380         return ERRNO_NULLPTR;
381     }
382 
383     let src_struct = match OhCloudExtCloudAsset::get_inner_ref(src, SafetyCheckId::CloudAsset) {
384         None => return ERRNO_WRONG_TYPE,
385         Some(v) => v,
386     };
387     *size = src_struct.size().as_ptr() as *const c_uchar;
388     *len = src_struct.size().len() as c_uint;
389     ERRNO_SUCCESS
390 }
391 
392 /// Get hash from an CloudAsset pointer.
393 #[no_mangle]
OhCloudExtCloudAssetGetHash( src: *const OhCloudExtCloudAsset, hash: *mut *const c_uchar, len: *mut c_uint, ) -> c_int394 pub unsafe extern "C" fn OhCloudExtCloudAssetGetHash(
395     src: *const OhCloudExtCloudAsset,
396     hash: *mut *const c_uchar,
397     len: *mut c_uint,
398 ) -> c_int {
399     if src.is_null() || hash.is_null() || len.is_null() {
400         return ERRNO_NULLPTR;
401     }
402 
403     let src_struct = match OhCloudExtCloudAsset::get_inner_ref(src, SafetyCheckId::CloudAsset) {
404         None => return ERRNO_WRONG_TYPE,
405         Some(v) => v,
406     };
407     *hash = src_struct.hash().as_ptr() as *const c_uchar;
408     *len = src_struct.hash().len() as c_uint;
409     ERRNO_SUCCESS
410 }
411 
412 /// Free a CloudAsset pointer.
413 #[no_mangle]
OhCloudExtCloudAssetFree(src: *mut OhCloudExtCloudAsset)414 pub unsafe extern "C" fn OhCloudExtCloudAssetFree(src: *mut OhCloudExtCloudAsset) {
415     let _ = OhCloudExtCloudAsset::from_ptr(src, SafetyCheckId::CloudAsset);
416 }
417 
418 /// Create a Database instance by database name, alias, and tables. Tables can be created by
419 /// basic_rust_types::HashMap, and its type should be HashMap<String, Table>. When passed in,
420 /// tables don't need to be freed again, because their management will be transferred to Database
421 /// instance.
422 #[no_mangle]
OhCloudExtDatabaseNew( name: *const c_uchar, name_len: c_uint, alias: *const c_uchar, alias_len: c_uint, tables: *mut OhCloudExtHashMap, ) -> *mut OhCloudExtDatabase423 pub unsafe extern "C" fn OhCloudExtDatabaseNew(
424     name: *const c_uchar,
425     name_len: c_uint,
426     alias: *const c_uchar,
427     alias_len: c_uint,
428     tables: *mut OhCloudExtHashMap,
429 ) -> *mut OhCloudExtDatabase {
430     let name = char_ptr_to_string(name, name_len);
431     let alias = char_ptr_to_string(alias, alias_len);
432 
433     if tables.is_null() {
434         let t = HashMap::new();
435         let db = types::Database::new(name, alias, t);
436         OhCloudExtDatabase::new(db, SafetyCheckId::Database).into_ptr() as *mut OhCloudExtDatabase
437     } else {
438         let tables = match OhCloudExtHashMap::get_inner(tables, SafetyCheckId::HashMap) {
439             None => return null_mut(),
440             Some(t) => t,
441         };
442         match tables {
443             HashMapCffi::Table(t) => {
444                 let db = types::Database::new(name, alias, t);
445                 OhCloudExtDatabase::new(db, SafetyCheckId::Database).into_ptr()
446                     as *mut OhCloudExtDatabase
447             }
448             _ => null_mut(),
449         }
450     }
451 }
452 
453 /// Get name from a Database pointer.
454 #[no_mangle]
OhCloudExtDatabaseGetName( db: *const OhCloudExtDatabase, name: *mut *const c_uchar, len: *mut c_uint, ) -> c_int455 pub unsafe extern "C" fn OhCloudExtDatabaseGetName(
456     db: *const OhCloudExtDatabase,
457     name: *mut *const c_uchar,
458     len: *mut c_uint,
459 ) -> c_int {
460     if db.is_null() || name.is_null() || len.is_null() {
461         return ERRNO_NULLPTR;
462     }
463 
464     let db_struct = match OhCloudExtDatabase::get_inner_ref(db, SafetyCheckId::Database) {
465         None => return ERRNO_WRONG_TYPE,
466         Some(v) => v,
467     };
468     *name = db_struct.name.as_ptr() as *const c_uchar;
469     *len = db_struct.name.len() as c_uint;
470     ERRNO_SUCCESS
471 }
472 
473 /// Get alias from a Database pointer.
474 #[no_mangle]
OhCloudExtDatabaseGetAlias( db: *const OhCloudExtDatabase, alias: *mut *const c_uchar, len: *mut c_uint, ) -> c_int475 pub unsafe extern "C" fn OhCloudExtDatabaseGetAlias(
476     db: *const OhCloudExtDatabase,
477     alias: *mut *const c_uchar,
478     len: *mut c_uint,
479 ) -> c_int {
480     if db.is_null() || alias.is_null() || len.is_null() {
481         return ERRNO_NULLPTR;
482     }
483 
484     let db_struct = match OhCloudExtDatabase::get_inner_ref(db, SafetyCheckId::Database) {
485         None => return ERRNO_WRONG_TYPE,
486         Some(v) => v,
487     };
488     *alias = db_struct.alias.as_ptr() as *const c_uchar;
489     *len = db_struct.alias.len() as c_uint;
490     ERRNO_SUCCESS
491 }
492 
493 /// Get hashmap of tables from a Database pointer. Parameter `tables` will be updated
494 /// to hold the output HashMap, and it should be freed by `HashMapFree`.
495 #[no_mangle]
OhCloudExtDatabaseGetTable( db: *const OhCloudExtDatabase, tables: *mut *const OhCloudExtHashMap, ) -> c_int496 pub unsafe extern "C" fn OhCloudExtDatabaseGetTable(
497     db: *const OhCloudExtDatabase,
498     tables: *mut *const OhCloudExtHashMap,
499 ) -> c_int {
500     if db.is_null() || tables.is_null() {
501         return ERRNO_NULLPTR;
502     }
503 
504     let db_struct = match OhCloudExtDatabase::get_inner_ref(db, SafetyCheckId::Database) {
505         None => return ERRNO_WRONG_TYPE,
506         Some(v) => v,
507     };
508     let tb_hashmap = HashMapCffi::Table(db_struct.tables.clone());
509     *tables = OhCloudExtHashMap::new(tb_hashmap, SafetyCheckId::HashMap).into_ptr()
510         as *const OhCloudExtHashMap;
511     ERRNO_SUCCESS
512 }
513 
514 /// Free a Database pointer.
515 #[no_mangle]
OhCloudExtDatabaseFree(src: *mut OhCloudExtDatabase)516 pub unsafe extern "C" fn OhCloudExtDatabaseFree(src: *mut OhCloudExtDatabase) {
517     let _ = OhCloudExtDatabase::from_ptr(src, SafetyCheckId::Database);
518 }
519 
520 /// Create a Table instance by table name, table alias, and vector of fields. Fields can be created
521 /// by basic_rust_types::Vector, and its type should be Vec<Field>. When passed in, fields don't
522 /// need to be freed again, because their management will be transferred to Table instance.
523 #[no_mangle]
OhCloudExtTableNew( name: *const c_uchar, name_len: c_uint, alias: *const c_uchar, alias_len: c_uint, fields: *mut OhCloudExtVector, ) -> *mut OhCloudExtTable524 pub unsafe extern "C" fn OhCloudExtTableNew(
525     name: *const c_uchar,
526     name_len: c_uint,
527     alias: *const c_uchar,
528     alias_len: c_uint,
529     fields: *mut OhCloudExtVector,
530 ) -> *mut OhCloudExtTable {
531     let name = char_ptr_to_string(name, name_len);
532     let alias = char_ptr_to_string(alias, alias_len);
533 
534     if fields.is_null() {
535         let f = vec![];
536         let tb = types::Table::new(name, alias, f);
537         OhCloudExtTable::new(tb, SafetyCheckId::Table).into_ptr() as *mut OhCloudExtTable
538     } else {
539         let fields = match OhCloudExtVector::get_inner(fields, SafetyCheckId::Vector) {
540             None => return null_mut(),
541             Some(v) => v,
542         };
543         match fields {
544             VectorCffi::Field(f) => {
545                 let tb = types::Table::new(name, alias, f);
546                 OhCloudExtTable::new(tb, SafetyCheckId::Table).into_ptr()
547             }
548             _ => null_mut(),
549         }
550     }
551 }
552 
553 /// Get name from a Table pointer.
554 #[no_mangle]
OhCloudExtTableGetName( tb: *const OhCloudExtTable, name: *mut *const c_uchar, len: *mut c_uint, ) -> c_int555 pub unsafe extern "C" fn OhCloudExtTableGetName(
556     tb: *const OhCloudExtTable,
557     name: *mut *const c_uchar,
558     len: *mut c_uint,
559 ) -> c_int {
560     if tb.is_null() || name.is_null() || len.is_null() {
561         return ERRNO_NULLPTR;
562     }
563 
564     let tb_struct = match OhCloudExtTable::get_inner_ref(tb, SafetyCheckId::Table) {
565         None => return ERRNO_WRONG_TYPE,
566         Some(v) => v,
567     };
568     *name = tb_struct.name.as_ptr() as *const c_uchar;
569     *len = tb_struct.name.len() as c_uint;
570     ERRNO_SUCCESS
571 }
572 
573 /// Get alias from a Table pointer.
574 #[no_mangle]
OhCloudExtTableGetAlias( tb: *const OhCloudExtTable, alias: *mut *const c_uchar, len: *mut c_uint, ) -> c_int575 pub unsafe extern "C" fn OhCloudExtTableGetAlias(
576     tb: *const OhCloudExtTable,
577     alias: *mut *const c_uchar,
578     len: *mut c_uint,
579 ) -> c_int {
580     if tb.is_null() || alias.is_null() || len.is_null() {
581         return ERRNO_NULLPTR;
582     }
583 
584     let tb_struct = match OhCloudExtTable::get_inner_ref(tb, SafetyCheckId::Table) {
585         None => return ERRNO_WRONG_TYPE,
586         Some(v) => v,
587     };
588     *alias = tb_struct.alias.as_ptr() as *const c_uchar;
589     *len = tb_struct.alias.len() as c_uint;
590     ERRNO_SUCCESS
591 }
592 
593 /// Get vector of fields from a Table pointer. Parameter `fields` be updated
594 /// to hold the output Vector, and it should be freed by `VectorFree`.
595 #[no_mangle]
OhCloudExtTableGetFields( tb: *const OhCloudExtTable, fields: *mut *const OhCloudExtVector, ) -> c_int596 pub unsafe extern "C" fn OhCloudExtTableGetFields(
597     tb: *const OhCloudExtTable,
598     fields: *mut *const OhCloudExtVector,
599 ) -> c_int {
600     if tb.is_null() || fields.is_null() {
601         return ERRNO_NULLPTR;
602     }
603 
604     let tb_struct = match OhCloudExtTable::get_inner_ref(tb, SafetyCheckId::Table) {
605         None => return ERRNO_WRONG_TYPE,
606         Some(v) => v,
607     };
608     let vec = VectorCffi::Field(tb_struct.fields.clone());
609     *fields = OhCloudExtVector::new(vec, SafetyCheckId::Vector).into_ptr();
610     ERRNO_SUCCESS
611 }
612 
613 /// Free a Table pointer.
614 #[no_mangle]
OhCloudExtTableFree(src: *mut OhCloudExtTable)615 pub unsafe extern "C" fn OhCloudExtTableFree(src: *mut OhCloudExtTable) {
616     let _ = OhCloudExtTable::from_ptr(src, SafetyCheckId::Table);
617 }
618 
619 #[inline]
c_bool_to_bool(src: u8) -> bool620 fn c_bool_to_bool(src: u8) -> bool {
621     src != 0
622 }
623 
624 /// FieldBuilder providing necessary information when create a Field.
625 #[repr(C)]
626 pub struct OhCloudExtFieldBuilder {
627     col_name: *const c_uchar,
628     col_name_len: c_uint,
629     alias: *const c_uchar,
630     alias_len: c_uint,
631     typ: c_uint,
632     primary: u8,
633     nullable: u8,
634 }
635 
636 /// Create a Field by column name, alias, type, primary, and nullable.
637 #[no_mangle]
OhCloudExtFieldNew( builder: *const OhCloudExtFieldBuilder, ) -> *mut OhCloudExtField638 pub unsafe extern "C" fn OhCloudExtFieldNew(
639     builder: *const OhCloudExtFieldBuilder,
640 ) -> *mut OhCloudExtField {
641     if builder.is_null() {
642         return null_mut();
643     }
644     let builder = &*builder;
645     let col_name = char_ptr_to_string(builder.col_name, builder.col_name_len);
646     let alias = char_ptr_to_string(builder.alias, builder.alias_len);
647     let typ = builder.typ as u8;
648     let primary = c_bool_to_bool(builder.primary);
649     let nullable = c_bool_to_bool(builder.nullable);
650     let fd = types::Field::new(col_name, alias, typ, primary, nullable);
651     OhCloudExtField::new(fd, SafetyCheckId::Field).into_ptr()
652 }
653 
654 /// Get column name from a Field pointer.
655 #[no_mangle]
OhCloudExtFieldGetColName( fd: *const OhCloudExtField, name: *mut *const c_uchar, len: *mut c_uint, ) -> c_int656 pub unsafe extern "C" fn OhCloudExtFieldGetColName(
657     fd: *const OhCloudExtField,
658     name: *mut *const c_uchar,
659     len: *mut c_uint,
660 ) -> c_int {
661     if fd.is_null() || name.is_null() || len.is_null() {
662         return ERRNO_NULLPTR;
663     }
664 
665     let fd_struct = match OhCloudExtField::get_inner_ref(fd, SafetyCheckId::Field) {
666         None => return ERRNO_WRONG_TYPE,
667         Some(v) => v,
668     };
669     *name = fd_struct.col_name.as_ptr() as *const c_uchar;
670     *len = fd_struct.col_name.len() as c_uint;
671     ERRNO_SUCCESS
672 }
673 
674 /// Get alias from a Field pointer.
675 #[no_mangle]
OhCloudExtFieldGetAlias( fd: *const OhCloudExtField, alias: *mut *const c_uchar, len: *mut c_uint, ) -> c_int676 pub unsafe extern "C" fn OhCloudExtFieldGetAlias(
677     fd: *const OhCloudExtField,
678     alias: *mut *const c_uchar,
679     len: *mut c_uint,
680 ) -> c_int {
681     if fd.is_null() || alias.is_null() || len.is_null() {
682         return ERRNO_NULLPTR;
683     }
684 
685     let fd_struct = match OhCloudExtField::get_inner_ref(fd, SafetyCheckId::Field) {
686         None => return ERRNO_WRONG_TYPE,
687         Some(v) => v,
688     };
689     *alias = fd_struct.alias.as_ptr() as *const c_uchar;
690     *len = fd_struct.alias.len() as c_uint;
691     ERRNO_SUCCESS
692 }
693 
694 /// Get type from a Field pointer.
695 #[no_mangle]
OhCloudExtFieldGetTyp( fd: *const OhCloudExtField, typ: *mut c_uint, ) -> c_int696 pub unsafe extern "C" fn OhCloudExtFieldGetTyp(
697     fd: *const OhCloudExtField,
698     typ: *mut c_uint,
699 ) -> c_int {
700     if fd.is_null() || typ.is_null() {
701         return ERRNO_NULLPTR;
702     }
703 
704     let fd_struct = match OhCloudExtField::get_inner_ref(fd, SafetyCheckId::Field) {
705         None => return ERRNO_WRONG_TYPE,
706         Some(v) => v,
707     };
708     *typ = fd_struct.typ as c_uint;
709     ERRNO_SUCCESS
710 }
711 
712 /// Check whether the Field is primary.
713 #[no_mangle]
OhCloudExtFieldGetPrimary( fd: *const OhCloudExtField, primary: *mut u8, ) -> c_int714 pub unsafe extern "C" fn OhCloudExtFieldGetPrimary(
715     fd: *const OhCloudExtField,
716     primary: *mut u8,
717 ) -> c_int {
718     if fd.is_null() || primary.is_null() {
719         return ERRNO_NULLPTR;
720     }
721 
722     let fd_struct = match OhCloudExtField::get_inner_ref(fd, SafetyCheckId::Field) {
723         None => return ERRNO_WRONG_TYPE,
724         Some(v) => v,
725     };
726     *primary = fd_struct.primary as u8;
727     ERRNO_SUCCESS
728 }
729 
730 /// Check whether the Field is nullable.
731 #[no_mangle]
OhCloudExtFieldGetNullable( fd: *const OhCloudExtField, nullable: *mut u8, ) -> c_int732 pub unsafe extern "C" fn OhCloudExtFieldGetNullable(
733     fd: *const OhCloudExtField,
734     nullable: *mut u8,
735 ) -> c_int {
736     if fd.is_null() || nullable.is_null() {
737         return ERRNO_NULLPTR;
738     }
739 
740     let fd_struct = match OhCloudExtField::get_inner_ref(fd, SafetyCheckId::Field) {
741         None => return ERRNO_WRONG_TYPE,
742         Some(v) => v,
743     };
744     *nullable = fd_struct.nullable as u8;
745     ERRNO_SUCCESS
746 }
747 
748 /// Free a Field pointer.
749 #[no_mangle]
OhCloudExtFieldFree(src: *mut OhCloudExtField)750 pub unsafe extern "C" fn OhCloudExtFieldFree(src: *mut OhCloudExtField) {
751     let _ = OhCloudExtField::from_ptr(src, SafetyCheckId::Field);
752 }
753 
754 /// Get user from a CloudInfo pointer.
755 #[no_mangle]
OhCloudExtCloudInfoGetUser( info: *const OhCloudExtCloudInfo, user: *mut c_int, ) -> c_int756 pub unsafe extern "C" fn OhCloudExtCloudInfoGetUser(
757     info: *const OhCloudExtCloudInfo,
758     user: *mut c_int,
759 ) -> c_int {
760     if info.is_null() || user.is_null() {
761         return ERRNO_NULLPTR;
762     }
763 
764     let info_struct = match OhCloudExtCloudInfo::get_inner_ref(info, SafetyCheckId::CloudInfo) {
765         None => return ERRNO_WRONG_TYPE,
766         Some(v) => v,
767     };
768     *user = info_struct.user;
769     ERRNO_SUCCESS
770 }
771 
772 /// Get id from a CloudInfo pointer.
773 #[no_mangle]
OhCloudExtCloudInfoGetId( info: *const OhCloudExtCloudInfo, id: *mut *const c_uchar, id_len: *mut c_uint, ) -> c_int774 pub unsafe extern "C" fn OhCloudExtCloudInfoGetId(
775     info: *const OhCloudExtCloudInfo,
776     id: *mut *const c_uchar,
777     id_len: *mut c_uint,
778 ) -> c_int {
779     if info.is_null() || id.is_null() || id_len.is_null() {
780         return ERRNO_NULLPTR;
781     }
782 
783     let info_struct = match OhCloudExtCloudInfo::get_inner_ref(info, SafetyCheckId::CloudInfo) {
784         None => return ERRNO_WRONG_TYPE,
785         Some(v) => v,
786     };
787     *id = info_struct.id.as_ptr() as *const c_uchar;
788     *id_len = info_struct.id.len() as c_uint;
789     ERRNO_SUCCESS
790 }
791 
792 /// Get total space from a CloudInfo pointer.
793 #[no_mangle]
OhCloudExtCloudInfoGetTotalSpace( info: *const OhCloudExtCloudInfo, total_space: *mut c_ulonglong, ) -> c_int794 pub unsafe extern "C" fn OhCloudExtCloudInfoGetTotalSpace(
795     info: *const OhCloudExtCloudInfo,
796     total_space: *mut c_ulonglong,
797 ) -> c_int {
798     if info.is_null() || total_space.is_null() {
799         return ERRNO_NULLPTR;
800     }
801 
802     let info_struct = match OhCloudExtCloudInfo::get_inner_ref(info, SafetyCheckId::CloudInfo) {
803         None => return ERRNO_WRONG_TYPE,
804         Some(v) => v,
805     };
806     *total_space = info_struct.total_space as c_ulonglong;
807     ERRNO_SUCCESS
808 }
809 
810 /// Get remain space from a CloudInfo pointer.
811 #[no_mangle]
OhCloudExtCloudInfoGetRemainSpace( info: *const OhCloudExtCloudInfo, remain_space: *mut c_ulonglong, ) -> c_int812 pub unsafe extern "C" fn OhCloudExtCloudInfoGetRemainSpace(
813     info: *const OhCloudExtCloudInfo,
814     remain_space: *mut c_ulonglong,
815 ) -> c_int {
816     if info.is_null() || remain_space.is_null() {
817         return ERRNO_NULLPTR;
818     }
819 
820     let info_struct = match OhCloudExtCloudInfo::get_inner_ref(info, SafetyCheckId::CloudInfo) {
821         None => return ERRNO_WRONG_TYPE,
822         Some(v) => v,
823     };
824     *remain_space = info_struct.remain_space as c_ulonglong;
825     ERRNO_SUCCESS
826 }
827 
828 /// Check whether a CloudInfo enables cloud sync.
829 #[no_mangle]
OhCloudExtCloudInfoEnabled( info: *const OhCloudExtCloudInfo, enable: *mut u8, ) -> c_int830 pub unsafe extern "C" fn OhCloudExtCloudInfoEnabled(
831     info: *const OhCloudExtCloudInfo,
832     enable: *mut u8,
833 ) -> c_int {
834     if info.is_null() || enable.is_null() {
835         return ERRNO_NULLPTR;
836     }
837 
838     let info_struct = match OhCloudExtCloudInfo::get_inner_ref(info, SafetyCheckId::CloudInfo) {
839         None => return ERRNO_WRONG_TYPE,
840         Some(v) => v,
841     };
842     *enable = info_struct.enable_cloud as u8;
843     ERRNO_SUCCESS
844 }
845 
846 /// Get hashmap of AppInfo from a CloudInfo pointer. Parameter `app_info` will be updated
847 /// to hold the output HashMap, and it should be freed by `HashMapFree`.
848 #[no_mangle]
OhCloudExtCloudInfoGetAppInfo( info: *const OhCloudExtCloudInfo, app_info: *mut *const OhCloudExtHashMap, ) -> c_int849 pub unsafe extern "C" fn OhCloudExtCloudInfoGetAppInfo(
850     info: *const OhCloudExtCloudInfo,
851     app_info: *mut *const OhCloudExtHashMap,
852 ) -> c_int {
853     if info.is_null() || app_info.is_null() {
854         return ERRNO_NULLPTR;
855     }
856 
857     let info_struct = match OhCloudExtCloudInfo::get_inner_ref(info, SafetyCheckId::CloudInfo) {
858         None => return ERRNO_WRONG_TYPE,
859         Some(v) => v,
860     };
861     let apps = HashMapCffi::AppInfo(info_struct.apps.clone());
862     *app_info = OhCloudExtHashMap::new(apps, SafetyCheckId::HashMap).into_ptr();
863     ERRNO_SUCCESS
864 }
865 
866 /// Free a CloudInfo pointer.
867 #[no_mangle]
OhCloudExtCloudInfoFree(info: *mut OhCloudExtCloudInfo)868 pub unsafe extern "C" fn OhCloudExtCloudInfoFree(info: *mut OhCloudExtCloudInfo) {
869     let _ = OhCloudExtCloudInfo::from_ptr(info, SafetyCheckId::CloudInfo);
870 }
871 
872 /// Get app id from an AppInfo pointer.
873 #[no_mangle]
OhCloudExtAppInfoGetAppId( info: *const OhCloudExtAppInfo, id: *mut *const c_uchar, id_len: *mut c_uint, ) -> c_int874 pub unsafe extern "C" fn OhCloudExtAppInfoGetAppId(
875     info: *const OhCloudExtAppInfo,
876     id: *mut *const c_uchar,
877     id_len: *mut c_uint,
878 ) -> c_int {
879     if info.is_null() || id.is_null() || id_len.is_null() {
880         return ERRNO_NULLPTR;
881     }
882 
883     let info_struct = match OhCloudExtAppInfo::get_inner_ref(info, SafetyCheckId::AppInfo) {
884         None => return ERRNO_WRONG_TYPE,
885         Some(v) => v,
886     };
887     *id = info_struct.app_id.as_ptr() as *const c_uchar;
888     *id_len = info_struct.app_id.len() as c_uint;
889     ERRNO_SUCCESS
890 }
891 
892 /// Get bundle name from an AppInfo pointer.
893 #[no_mangle]
OhCloudExtAppInfoGetBundleName( info: *const OhCloudExtAppInfo, id: *mut *const c_uchar, id_len: *mut c_uint, ) -> c_int894 pub unsafe extern "C" fn OhCloudExtAppInfoGetBundleName(
895     info: *const OhCloudExtAppInfo,
896     id: *mut *const c_uchar,
897     id_len: *mut c_uint,
898 ) -> c_int {
899     if info.is_null() || id.is_null() || id_len.is_null() {
900         return ERRNO_NULLPTR;
901     }
902 
903     let info_struct = match OhCloudExtAppInfo::get_inner_ref(info, SafetyCheckId::AppInfo) {
904         None => return ERRNO_WRONG_TYPE,
905         Some(v) => v,
906     };
907     *id = info_struct.bundle_name.as_ptr() as *const c_uchar;
908     *id_len = info_struct.bundle_name.len() as c_uint;
909     ERRNO_SUCCESS
910 }
911 
912 /// Check whether an AppInfo pointer allows cloud switch.
913 #[no_mangle]
OhCloudExtAppInfoGetCloudSwitch( info: *const OhCloudExtAppInfo, switch: *mut u8, ) -> c_int914 pub unsafe extern "C" fn OhCloudExtAppInfoGetCloudSwitch(
915     info: *const OhCloudExtAppInfo,
916     switch: *mut u8,
917 ) -> c_int {
918     if info.is_null() || switch.is_null() {
919         return ERRNO_NULLPTR;
920     }
921 
922     let info_struct = match OhCloudExtAppInfo::get_inner_ref(info, SafetyCheckId::AppInfo) {
923         None => return ERRNO_WRONG_TYPE,
924         Some(v) => v,
925     };
926     *switch = info_struct.cloud_switch as u8;
927     ERRNO_SUCCESS
928 }
929 
930 /// Get instance id from an AppInfo pointer.
931 #[no_mangle]
OhCloudExtAppInfoGetInstanceId( info: *const OhCloudExtAppInfo, id: *mut c_int, ) -> c_int932 pub unsafe extern "C" fn OhCloudExtAppInfoGetInstanceId(
933     info: *const OhCloudExtAppInfo,
934     id: *mut c_int,
935 ) -> c_int {
936     if info.is_null() || id.is_null() {
937         return ERRNO_NULLPTR;
938     }
939 
940     let info_struct = match OhCloudExtAppInfo::get_inner_ref(info, SafetyCheckId::AppInfo) {
941         None => return ERRNO_WRONG_TYPE,
942         Some(v) => v,
943     };
944     *id = info_struct.instance_id;
945     ERRNO_SUCCESS
946 }
947 
948 /// Free a AppInfo ptr.
949 #[no_mangle]
OhCloudExtAppInfoFree(info: *mut OhCloudExtAppInfo)950 pub unsafe extern "C" fn OhCloudExtAppInfoFree(info: *mut OhCloudExtAppInfo) {
951     let _ = OhCloudExtAppInfo::from_ptr(info, SafetyCheckId::AppInfo);
952 }
953 
954 /// Get version from a SchemaMeta pointer.
955 #[no_mangle]
OhCloudExtSchemaMetaGetVersion( schema: *mut OhCloudExtSchemaMeta, version: *mut c_int, ) -> c_int956 pub unsafe extern "C" fn OhCloudExtSchemaMetaGetVersion(
957     schema: *mut OhCloudExtSchemaMeta,
958     version: *mut c_int,
959 ) -> c_int {
960     if schema.is_null() || version.is_null() {
961         return ERRNO_NULLPTR;
962     }
963 
964     let schema_struct = match OhCloudExtSchemaMeta::get_inner_ref(schema, SafetyCheckId::SchemaMeta)
965     {
966         None => return ERRNO_WRONG_TYPE,
967         Some(v) => v,
968     };
969     *version = schema_struct.version();
970     ERRNO_SUCCESS
971 }
972 
973 /// Get bundle name from a SchemaMeta pointer.
974 #[no_mangle]
OhCloudExtSchemaMetaGetBundleName( schema: *mut OhCloudExtSchemaMeta, name: *mut *const c_uchar, len: *mut c_uint, ) -> c_int975 pub unsafe extern "C" fn OhCloudExtSchemaMetaGetBundleName(
976     schema: *mut OhCloudExtSchemaMeta,
977     name: *mut *const c_uchar,
978     len: *mut c_uint,
979 ) -> c_int {
980     if schema.is_null() || name.is_null() || len.is_null() {
981         return ERRNO_NULLPTR;
982     }
983 
984     let schema_struct = match OhCloudExtSchemaMeta::get_inner_ref(schema, SafetyCheckId::SchemaMeta)
985     {
986         None => return ERRNO_WRONG_TYPE,
987         Some(v) => v,
988     };
989     *name = schema_struct.bundle_name().as_ptr() as *const c_uchar;
990     *len = schema_struct.bundle_name().len() as c_uint;
991     ERRNO_SUCCESS
992 }
993 
994 /// Get a vector of databases from a SchemaMeta pointer. Parameter `dbs` be updated
995 /// to hold the output Vector, and it should be freed by `VectorFree`.
996 #[no_mangle]
OhCloudExtSchemaMetaGetDatabases( schema: *mut OhCloudExtSchemaMeta, dbs: *mut *const OhCloudExtVector, ) -> c_int997 pub unsafe extern "C" fn OhCloudExtSchemaMetaGetDatabases(
998     schema: *mut OhCloudExtSchemaMeta,
999     dbs: *mut *const OhCloudExtVector,
1000 ) -> c_int {
1001     if schema.is_null() || dbs.is_null() {
1002         return ERRNO_NULLPTR;
1003     }
1004 
1005     let schema_struct = match OhCloudExtSchemaMeta::get_inner_ref(schema, SafetyCheckId::SchemaMeta)
1006     {
1007         None => return ERRNO_WRONG_TYPE,
1008         Some(v) => v,
1009     };
1010     let databases = schema_struct.databases();
1011     let vec = VectorCffi::Database(databases.to_vec());
1012     *dbs = OhCloudExtVector::new(vec, SafetyCheckId::Vector).into_ptr();
1013     ERRNO_SUCCESS
1014 }
1015 
1016 /// Free a SchemaMeta pointer.
1017 #[no_mangle]
OhCloudExtSchemaMetaFree(schema: *mut OhCloudExtSchemaMeta)1018 pub unsafe extern "C" fn OhCloudExtSchemaMetaFree(schema: *mut OhCloudExtSchemaMeta) {
1019     let _ = OhCloudExtSchemaMeta::from_ptr(schema, SafetyCheckId::SchemaMeta);
1020 }
1021 
1022 /// Create a RelationSet instance by bundle name, and relations. Relations can be created by
1023 /// basic_rust_types::HashMap, and its type should be HashMap<String, (u32, u32)>. When passed in,
1024 /// tables don't need to be freed again, because their management will be transferred to RelationSet
1025 /// instance.
1026 #[no_mangle]
OhCloudExtRelationSetNew( bundle_name: *const c_uchar, len: c_uint, expire_time: c_longlong, relations: *mut OhCloudExtHashMap, ) -> *mut OhCloudExtRelationSet1027 pub unsafe extern "C" fn OhCloudExtRelationSetNew(
1028     bundle_name: *const c_uchar,
1029     len: c_uint,
1030     expire_time: c_longlong,
1031     relations: *mut OhCloudExtHashMap,
1032 ) -> *mut OhCloudExtRelationSet {
1033     let name = char_ptr_to_string(bundle_name, len);
1034 
1035     if relations.is_null() {
1036         let re = HashMap::default();
1037         let relation = cloud_service::RelationSet::new(name, expire_time, re);
1038         OhCloudExtRelationSet::new(relation, SafetyCheckId::RelationSet).into_ptr()
1039     } else {
1040         let relations = match OhCloudExtHashMap::get_inner(relations, SafetyCheckId::HashMap) {
1041             None => return null_mut(),
1042             Some(v) => v,
1043         };
1044         match relations {
1045             HashMapCffi::String(re) => {
1046                 let relation = cloud_service::RelationSet::new(name, expire_time, re);
1047                 OhCloudExtRelationSet::new(relation, SafetyCheckId::RelationSet).into_ptr()
1048             }
1049             _ => null_mut(),
1050         }
1051     }
1052 }
1053 
1054 /// Get bundle name from a RelationSet pointer.
1055 #[no_mangle]
OhCloudExtRelationSetGetBundleName( relation: *mut OhCloudExtRelationSet, bundle_name: *mut *const c_uchar, len: *mut c_uint, ) -> c_int1056 pub unsafe extern "C" fn OhCloudExtRelationSetGetBundleName(
1057     relation: *mut OhCloudExtRelationSet,
1058     bundle_name: *mut *const c_uchar,
1059     len: *mut c_uint,
1060 ) -> c_int {
1061     if relation.is_null() || bundle_name.is_null() || len.is_null() {
1062         return ERRNO_NULLPTR;
1063     }
1064 
1065     let relation_struct =
1066         match OhCloudExtRelationSet::get_inner_ref(relation, SafetyCheckId::RelationSet) {
1067             None => return ERRNO_WRONG_TYPE,
1068             Some(v) => v,
1069         };
1070     *bundle_name = relation_struct.bundle_name.as_ptr() as *const c_uchar;
1071     *len = relation_struct.bundle_name.len() as c_uint;
1072     ERRNO_SUCCESS
1073 }
1074 
1075 /// Get expire time from a RelationSet pointer.
1076 #[no_mangle]
OhCloudExtRelationSetGetExpireTime( relation: *mut OhCloudExtRelationSet, expire_time: *mut c_ulonglong, ) -> c_int1077 pub unsafe extern "C" fn OhCloudExtRelationSetGetExpireTime(
1078     relation: *mut OhCloudExtRelationSet,
1079     expire_time: *mut c_ulonglong,
1080 ) -> c_int {
1081     if relation.is_null() || expire_time.is_null() {
1082         return ERRNO_NULLPTR;
1083     }
1084 
1085     let relation_struct =
1086         match OhCloudExtRelationSet::get_inner_ref(relation, SafetyCheckId::RelationSet) {
1087             None => return ERRNO_WRONG_TYPE,
1088             Some(v) => v,
1089         };
1090     *expire_time = relation_struct.expire_time as c_ulonglong;
1091     ERRNO_SUCCESS
1092 }
1093 
1094 /// Get relations from a RelationSet pointer. Parameter `relations` be updated
1095 /// to hold the output HashMap, and it should be freed by `HashMapFree`.
1096 #[no_mangle]
OhCloudExtRelationSetGetRelations( relation: *mut OhCloudExtRelationSet, relations: *mut *const OhCloudExtHashMap, ) -> c_int1097 pub unsafe extern "C" fn OhCloudExtRelationSetGetRelations(
1098     relation: *mut OhCloudExtRelationSet,
1099     relations: *mut *const OhCloudExtHashMap,
1100 ) -> c_int {
1101     if relation.is_null() || relations.is_null() {
1102         return ERRNO_NULLPTR;
1103     }
1104 
1105     let relation_struct =
1106         match OhCloudExtRelationSet::get_inner_ref(relation, SafetyCheckId::RelationSet) {
1107             None => return ERRNO_WRONG_TYPE,
1108             Some(v) => v,
1109         };
1110     let res = relation_struct.relations();
1111     let hashmap = HashMapCffi::String(res.clone());
1112     *relations = OhCloudExtHashMap::new(hashmap, SafetyCheckId::HashMap).into_ptr();
1113     ERRNO_SUCCESS
1114 }
1115 
1116 /// Free a RelationSet pointer.
1117 #[no_mangle]
OhCloudExtRelationSetFree(re: *mut OhCloudExtRelationSet)1118 pub unsafe extern "C" fn OhCloudExtRelationSetFree(re: *mut OhCloudExtRelationSet) {
1119     let _ = OhCloudExtRelationSet::from_ptr(re, SafetyCheckId::RelationSet);
1120 }
1121 
1122 /// Get the next cursor from a CloudDbData pointer.
1123 #[no_mangle]
OhCloudExtCloudDbDataGetNextCursor( data: *mut OhCloudExtCloudDbData, cursor: *mut *const c_uchar, len: *mut c_uint, ) -> c_int1124 pub unsafe extern "C" fn OhCloudExtCloudDbDataGetNextCursor(
1125     data: *mut OhCloudExtCloudDbData,
1126     cursor: *mut *const c_uchar,
1127     len: *mut c_uint,
1128 ) -> c_int {
1129     if data.is_null() || cursor.is_null() || len.is_null() {
1130         return ERRNO_NULLPTR;
1131     }
1132 
1133     let data_struct = match OhCloudExtCloudDbData::get_inner_ref(data, SafetyCheckId::CloudDbData) {
1134         None => return ERRNO_WRONG_TYPE,
1135         Some(v) => v,
1136     };
1137     *cursor = data_struct.next_cursor.as_ptr() as *const c_uchar;
1138     *len = data_struct.next_cursor.len() as c_uint;
1139     ERRNO_SUCCESS
1140 }
1141 
1142 /// Check whether a CloudDbData has more data.
1143 #[no_mangle]
OhCloudExtCloudDbDataGetHasMore( data: *mut OhCloudExtCloudDbData, has_more: *mut u8, ) -> c_int1144 pub unsafe extern "C" fn OhCloudExtCloudDbDataGetHasMore(
1145     data: *mut OhCloudExtCloudDbData,
1146     has_more: *mut u8,
1147 ) -> c_int {
1148     if data.is_null() || has_more.is_null() {
1149         return ERRNO_NULLPTR;
1150     }
1151 
1152     let data_struct = match OhCloudExtCloudDbData::get_inner_ref(data, SafetyCheckId::CloudDbData) {
1153         None => return ERRNO_WRONG_TYPE,
1154         Some(v) => v,
1155     };
1156     *has_more = data_struct.has_more as u8;
1157     ERRNO_SUCCESS
1158 }
1159 
1160 /// Get vector of values from a CloudDbData pointer. Parameter `values` will be updated
1161 /// to hold the output Vec<ValueBucket>, and it should be freed by `VectorFree`.
1162 #[no_mangle]
OhCloudExtCloudDbDataGetValues( data: *mut OhCloudExtCloudDbData, values: *mut *const OhCloudExtVector, ) -> c_int1163 pub unsafe extern "C" fn OhCloudExtCloudDbDataGetValues(
1164     data: *mut OhCloudExtCloudDbData,
1165     values: *mut *const OhCloudExtVector,
1166 ) -> c_int {
1167     if data.is_null() || values.is_null() {
1168         return ERRNO_NULLPTR;
1169     }
1170 
1171     let data_struct = match OhCloudExtCloudDbData::get_inner_ref(data, SafetyCheckId::CloudDbData) {
1172         None => return ERRNO_WRONG_TYPE,
1173         Some(v) => v,
1174     };
1175     let vec = VectorCffi::ValueBucket(data_struct.values.clone());
1176     *values = OhCloudExtVector::new(vec, SafetyCheckId::Vector).into_ptr();
1177     ERRNO_SUCCESS
1178 }
1179 
1180 /// Free a CloudDbData pointer.
1181 #[no_mangle]
OhCloudExtCloudDbDataFree(src: *mut OhCloudExtCloudDbData)1182 pub unsafe extern "C" fn OhCloudExtCloudDbDataFree(src: *mut OhCloudExtCloudDbData) {
1183     let _ = OhCloudExtCloudDbData::from_ptr(src, SafetyCheckId::CloudDbData);
1184 }
1185 
1186 #[repr(C)]
1187 pub struct OhCloudExtKeyName {
1188     key: *const c_uchar,
1189     key_len: c_uint,
1190 }
1191 
1192 #[no_mangle]
OhCloudExtKeyNameNew(key: *const c_uchar, key_len: c_uint) -> OhCloudExtKeyName1193 pub unsafe extern "C" fn OhCloudExtKeyNameNew(key: *const c_uchar, key_len: c_uint) -> OhCloudExtKeyName {
1194     let key_name = OhCloudExtKeyName { key, key_len };
1195     key_name
1196 }
1197 
1198 /// Get keys from a ValueBucket pointer.
1199 #[no_mangle]
OhCloudExtValueBucketGetKeys( vb: *mut OhCloudExtValueBucket, keys: *mut *const OhCloudExtVector, keys_len: *mut c_uint, ) -> c_int1200 pub unsafe extern "C" fn OhCloudExtValueBucketGetKeys(
1201     vb: *mut OhCloudExtValueBucket,
1202     keys: *mut *const OhCloudExtVector,
1203     keys_len: *mut c_uint,
1204 ) -> c_int {
1205     if vb.is_null() || keys.is_null() || keys_len.is_null() {
1206         return ERRNO_NULLPTR;
1207     }
1208 
1209     let vb_struct = match OhCloudExtValueBucket::get_inner_ref(vb, SafetyCheckId::ValueBucket) {
1210         None => return ERRNO_WRONG_TYPE,
1211         Some(v) => v,
1212     };
1213 
1214     let keys_vec = vb_struct.0.clone().into_keys().collect::<Vec<String>>();
1215     *keys_len = keys_vec.len() as c_uint;
1216     let vec = VectorCffi::String(keys_vec);
1217     *keys = OhCloudExtVector::new(vec, SafetyCheckId::Vector).into_ptr();
1218     ERRNO_SUCCESS
1219 }
1220 
1221 /// Gets Value from a ValueBucket pointer.
1222 #[no_mangle]
OhCloudExtValueBucketGetValue( vb: *mut OhCloudExtValueBucket, key_name: OhCloudExtKeyName, typ: *mut OhCloudExtValueType, content: *mut *const c_void, len: *mut c_uint, ) -> c_int1223 pub unsafe extern "C" fn OhCloudExtValueBucketGetValue(
1224     vb: *mut OhCloudExtValueBucket,
1225     key_name: OhCloudExtKeyName,
1226     typ: *mut OhCloudExtValueType,
1227     content: *mut *const c_void,
1228     len: *mut c_uint,
1229 ) -> c_int {
1230     let key = key_name.key;
1231     let key_len = key_name.key_len;
1232 
1233     if vb.is_null() || key.is_null() || typ.is_null() || content.is_null() || len.is_null() {
1234         return ERRNO_NULLPTR;
1235     }
1236 
1237     let name = char_ptr_to_string(key, key_len);
1238 
1239     let vb_struct = match OhCloudExtValueBucket::get_inner_ref(vb, SafetyCheckId::ValueBucket) {
1240         None => return ERRNO_WRONG_TYPE,
1241         Some(v) => v,
1242     };
1243 
1244     let value_struct = match vb_struct.0.get(&name) {
1245         None => return ERRNO_INVALID_KEY,
1246         Some(v) => v,
1247     };
1248 
1249     match value_struct {
1250         ipc_conn::FieldRaw::Null => {
1251             *typ = OhCloudExtValueType::EMPTY;
1252             *content = null();
1253             *len = 0;
1254         }
1255         ipc_conn::FieldRaw::Number(i) => {
1256             *typ = OhCloudExtValueType::INT;
1257             *content = i as *const i64 as *const c_void;
1258         }
1259         ipc_conn::FieldRaw::Real(f) => {
1260             *typ = OhCloudExtValueType::FLOAT;
1261             *content = f as *const f64 as *const c_void;
1262         }
1263         ipc_conn::FieldRaw::Text(s) => {
1264             *typ = OhCloudExtValueType::STRING;
1265             *content = s.as_ptr() as *const c_void;
1266             *len = s.len() as c_uint;
1267         }
1268         ipc_conn::FieldRaw::Bool(b) => {
1269             *typ = OhCloudExtValueType::BOOL;
1270             *content = b as *const bool as *const c_void;
1271         }
1272         ipc_conn::FieldRaw::Blob(b) => {
1273             *typ = OhCloudExtValueType::BYTES;
1274             *content = b.as_ptr() as *const c_void;
1275             *len = b.len() as c_uint;
1276         }
1277         ipc_conn::FieldRaw::Asset(a) => {
1278             *typ = OhCloudExtValueType::ASSET;
1279             *content = OhCloudExtCloudAsset::new(a.clone(), SafetyCheckId::CloudAsset).into_ptr()
1280                 as *mut c_void;
1281         }
1282         ipc_conn::FieldRaw::Assets(a) => {
1283             *typ = OhCloudExtValueType::ASSETS;
1284             let vec = VectorCffi::CloudAsset(a.0.to_vec());
1285             *content = OhCloudExtVector::new(vec, SafetyCheckId::Vector).into_ptr() as *mut c_void;
1286             *len = a.0.len() as c_uint;
1287         }
1288     }
1289 
1290     ERRNO_SUCCESS
1291 }
1292 
1293 /// Free a ValueBucket ptr.
1294 #[no_mangle]
OhCloudExtValueBucketFree(info: *mut OhCloudExtValueBucket)1295 pub unsafe extern "C" fn OhCloudExtValueBucketFree(info: *mut OhCloudExtValueBucket) {
1296     let _ = OhCloudExtValueBucket::from_ptr(info, SafetyCheckId::ValueBucket);
1297 }
1298 
1299 #[cfg(test)]
1300 mod test {
1301     use crate::c_adapter::basic_rust_types::{
1302         OhCloudExtHashMap, OhCloudExtRustType, OhCloudExtVector, OhCloudExtVectorNew,
1303         OhCloudExtVectorPush,
1304     };
1305     use crate::c_adapter::cloud_ext_types::*;
1306 
1307     /// UT test for Value creation and destruction.
1308     ///
1309     /// # Title
1310     /// ut_value_int
1311     ///
1312     /// # Brief
1313     /// 1. Create a Value::Int.
1314     /// 2. Get values from it.
1315     /// 3. Free the value ptr.
1316     /// 4. No error and memory leak should happen.
1317     #[test]
ut_value_int()1318     fn ut_value_int() {
1319         unsafe {
1320             let mut src = 1_i64;
1321             let value = OhCloudExtValueNew(
1322                 OhCloudExtValueType::INT,
1323                 &mut src as *mut _ as *mut c_void,
1324                 0,
1325             );
1326             assert!(!value.is_null());
1327 
1328             let mut typ = OhCloudExtValueType::EMPTY;
1329             let mut val: *mut c_uint = null_mut();
1330             let mut length = 1 as c_uint;
1331             assert_eq!(
1332                 OhCloudExtValueGetContent(
1333                     value,
1334                     &mut typ as *mut OhCloudExtValueType,
1335                     &mut val as *mut _ as *mut *const c_void,
1336                     &mut length as *mut _ as *mut c_uint
1337                 ),
1338                 ERRNO_SUCCESS
1339             );
1340             assert_eq!(*val as i64, src);
1341             assert_eq!(typ, OhCloudExtValueType::INT);
1342             OhCloudExtValueFree(value);
1343         }
1344     }
1345 
get_asset_ptr() -> *mut OhCloudExtCloudAsset1346     unsafe fn get_asset_ptr() -> *mut OhCloudExtCloudAsset {
1347         let temp = "temp";
1348         let mut builder = OhCloudExtCloudAssetBuilder {
1349             version: 0,
1350             status: asset_loader::AssetStatus::Normal,
1351             expires_time: 0,
1352             id: temp.as_ptr() as *const c_uchar,
1353             id_len: 4,
1354             name: temp.as_ptr() as *const c_uchar,
1355             name_len: 4,
1356             uri: temp.as_ptr() as *const c_uchar,
1357             uri_len: 4,
1358             local_path: temp.as_ptr() as *const c_uchar,
1359             local_path_len: 4,
1360             create_time: temp.as_ptr() as *const c_uchar,
1361             create_time_len: 4,
1362             modify_time: temp.as_ptr() as *const c_uchar,
1363             modify_time_len: 4,
1364             size: temp.as_ptr() as *const c_uchar,
1365             size_len: 4,
1366             hash: temp.as_ptr() as *const c_uchar,
1367             hash_len: 4,
1368         };
1369         let asset = OhCloudExtCloudAssetNew(&mut builder as *mut OhCloudExtCloudAssetBuilder);
1370         assert!(!asset.is_null());
1371         asset
1372     }
1373 
1374     /// UT test for Value creation and destruction.
1375     ///
1376     /// # Title
1377     /// ut_value_asset
1378     ///
1379     /// # Brief
1380     /// 1. Create a Value::Asset.
1381     /// 2. Get values from it.
1382     /// 3. Free the value ptr.
1383     /// 4. No error and memory leak should happen.
1384     #[test]
ut_value_asset()1385     fn ut_value_asset() {
1386         unsafe {
1387             let asset = get_asset_ptr();
1388             let value = OhCloudExtValueNew(OhCloudExtValueType::ASSET, asset as *mut c_void, 0);
1389             assert!(!value.is_null());
1390 
1391             let mut typ = OhCloudExtValueType::EMPTY;
1392             let mut val: *mut OhCloudExtCloudAsset = null_mut();
1393             let mut length = 1 as c_uint;
1394             assert_eq!(
1395                 OhCloudExtValueGetContent(
1396                     value,
1397                     &mut typ as *mut OhCloudExtValueType,
1398                     &mut val as *mut _ as *mut *const c_void,
1399                     &mut length as *mut _ as *mut c_uint
1400                 ),
1401                 ERRNO_SUCCESS
1402             );
1403             assert!(!val.is_null());
1404             assert_eq!(typ, OhCloudExtValueType::ASSET);
1405             OhCloudExtValueFree(value);
1406         }
1407     }
1408 
1409     /// UT test for Value creation and destruction.
1410     ///
1411     /// # Title
1412     /// ut_value_assets
1413     ///
1414     /// # Brief
1415     /// 1. Create a Value::Assets.
1416     /// 2. Get values from it.
1417     /// 3. Free the value ptr.
1418     /// 4. No error and memory leak should happen.
1419     #[test]
ut_value_assets()1420     fn ut_value_assets() {
1421         unsafe {
1422             let asset = get_asset_ptr();
1423             let vec = OhCloudExtVectorNew(OhCloudExtRustType::CLOUD_ASSET);
1424             assert!(!vec.is_null());
1425             assert_eq!(
1426                 OhCloudExtVectorPush(vec, asset as *mut c_void, 0),
1427                 ERRNO_SUCCESS
1428             );
1429             let value = OhCloudExtValueNew(OhCloudExtValueType::ASSETS, vec as *mut c_void, 0);
1430             assert!(!value.is_null());
1431 
1432             let mut typ = OhCloudExtValueType::EMPTY;
1433             let mut val: *mut OhCloudExtCloudAsset = null_mut();
1434             let mut length = 1 as c_uint;
1435             assert_eq!(
1436                 OhCloudExtValueGetContent(
1437                     value,
1438                     &mut typ as *mut OhCloudExtValueType,
1439                     &mut val as *mut _ as *mut *const c_void,
1440                     &mut length as *mut _ as *mut c_uint
1441                 ),
1442                 ERRNO_SUCCESS
1443             );
1444             assert!(!val.is_null());
1445             assert_eq!(typ, OhCloudExtValueType::ASSETS);
1446             let assets_struct =
1447                 OhCloudExtVector::get_inner(val as *mut OhCloudExtVector, SafetyCheckId::Vector)
1448                     .unwrap();
1449             match assets_struct {
1450                 VectorCffi::CloudAsset(v) => {
1451                     assert_eq!(v.len(), 1);
1452                 }
1453                 _ => panic!("Value typ mismatches with Assets"),
1454             }
1455             OhCloudExtValueFree(value);
1456         }
1457     }
1458 
1459     /// UT test for Database creation and destruction.
1460     ///
1461     /// # Title
1462     /// ut_database
1463     ///
1464     /// # Brief
1465     /// 1. Create a Database.
1466     /// 2. Get tables and name from it.
1467     /// 3. Free the Database ptr.
1468     /// 4. No error and memory leak should happen.
1469     #[test]
ut_database()1470     fn ut_database() {
1471         unsafe {
1472             let temp = "temp";
1473             let db = OhCloudExtDatabaseNew(
1474                 temp.as_ptr() as *const c_uchar,
1475                 temp.len() as c_uint,
1476                 null_mut(),
1477                 0,
1478                 null_mut(),
1479             );
1480             assert!(!db.is_null());
1481             let mut name: *mut c_uchar = null_mut();
1482             let mut length = 1 as c_uint;
1483             assert_eq!(
1484                 OhCloudExtDatabaseGetAlias(
1485                     db,
1486                     &mut name as *mut _ as *mut *const c_uchar,
1487                     &mut length as *mut _ as *mut c_uint
1488                 ),
1489                 ERRNO_SUCCESS
1490             );
1491             let id = &*slice_from_raw_parts(name as *const u8, length as usize);
1492             assert!(id.is_empty());
1493             assert_eq!(length, 0);
1494             let mut map: *mut OhCloudExtHashMap = null_mut();
1495             assert_eq!(
1496                 OhCloudExtDatabaseGetTable(db, &mut map as *mut _ as *mut *const OhCloudExtHashMap),
1497                 ERRNO_SUCCESS
1498             );
1499             assert!(!map.is_null());
1500             let map_struct = OhCloudExtHashMap::get_inner(map, SafetyCheckId::HashMap).unwrap();
1501             match map_struct {
1502                 HashMapCffi::Table(h) => {
1503                     assert!(h.is_empty());
1504                 }
1505                 _ => panic!("Db Table Map mismatches with Table"),
1506             }
1507             OhCloudExtDatabaseFree(db);
1508         }
1509     }
1510 
1511     /// UT test for Table creation and destruction.
1512     ///
1513     /// # Title
1514     /// ut_table
1515     ///
1516     /// # Brief
1517     /// 1. Create a Table.
1518     /// 2. Get fields and table name from it.
1519     /// 3. Free the Table ptr.
1520     /// 4. No error and memory leak should happen.
1521     #[test]
ut_table()1522     fn ut_table() {
1523         unsafe {
1524             let temp = "temp";
1525             let tb = OhCloudExtTableNew(
1526                 temp.as_ptr() as *const c_uchar,
1527                 temp.len() as c_uint,
1528                 null_mut(),
1529                 0,
1530                 null_mut(),
1531             );
1532             assert!(!tb.is_null());
1533             let mut name: *mut c_uchar = null_mut();
1534             let mut length = 1 as c_uint;
1535             assert_eq!(
1536                 OhCloudExtTableGetName(
1537                     tb,
1538                     &mut name as *mut _ as *mut *const c_uchar,
1539                     &mut length as *mut _ as *mut c_uint
1540                 ),
1541                 ERRNO_SUCCESS
1542             );
1543             let tb_name = &*slice_from_raw_parts(name as *const u8, length as usize);
1544             assert_eq!(tb_name, temp.as_bytes());
1545             assert_eq!(length as usize, temp.len());
1546             let mut vec: *mut OhCloudExtVector = null_mut();
1547             assert_eq!(
1548                 OhCloudExtTableGetFields(tb, &mut vec as *mut _ as *mut *const OhCloudExtVector),
1549                 ERRNO_SUCCESS
1550             );
1551             assert!(!vec.is_null());
1552             let vec_struct = OhCloudExtVector::get_inner(vec, SafetyCheckId::Vector).unwrap();
1553             match vec_struct {
1554                 VectorCffi::Field(f) => {
1555                     assert!(f.is_empty());
1556                 }
1557                 _ => panic!("Table fields mismatches with Vec<Field>"),
1558             }
1559             OhCloudExtTableFree(tb);
1560         }
1561     }
1562 
1563     /// UT test for Field creation and destruction.
1564     ///
1565     /// # Title
1566     /// ut_field
1567     ///
1568     /// # Brief
1569     /// 1. Create a Field.
1570     /// 2. Get name from it.
1571     /// 3. Free the Field ptr.
1572     /// 4. No error and memory leak should happen.
1573     #[test]
ut_field()1574     fn ut_field() {
1575         unsafe {
1576             let temp = "temp";
1577             let fd = OhCloudExtFieldNew(null_mut());
1578             assert!(fd.is_null());
1579             let builder = OhCloudExtFieldBuilder {
1580                 col_name: temp.as_ptr() as *const c_uchar,
1581                 col_name_len: temp.len() as c_uint,
1582                 alias: temp.as_ptr() as *const c_uchar,
1583                 alias_len: temp.len() as c_uint,
1584                 typ: 0,
1585                 primary: 0,
1586                 nullable: 0,
1587             };
1588             let fd = OhCloudExtFieldNew(&builder as *const OhCloudExtFieldBuilder);
1589             assert!(!fd.is_null());
1590 
1591             let mut name: *mut c_uchar = null_mut();
1592             let mut length = 1 as c_uint;
1593             assert_eq!(
1594                 OhCloudExtFieldGetAlias(
1595                     fd,
1596                     &mut name as *mut _ as *mut *const c_uchar,
1597                     &mut length as *mut _ as *mut c_uint
1598                 ),
1599                 ERRNO_SUCCESS
1600             );
1601             let fd_alias = &*slice_from_raw_parts(name as *const u8, length as usize);
1602             assert_eq!(fd_alias, temp.as_bytes());
1603             assert_eq!(length as usize, temp.len());
1604             let mut bool = true;
1605             assert_eq!(
1606                 OhCloudExtFieldGetNullable(fd, &mut bool as *mut _ as *mut u8),
1607                 ERRNO_SUCCESS
1608             );
1609             assert!(!bool);
1610             OhCloudExtFieldFree(fd);
1611         }
1612     }
1613 
1614     /// UT test for RelationSet creation and destruction.
1615     ///
1616     /// # Title
1617     /// ut_relation_set
1618     ///
1619     /// # Brief
1620     /// 1. Create a RelationSet.
1621     /// 2. Get name from it.
1622     /// 3. Free the RelationSet ptr.
1623     /// 4. No error and memory leak should happen.
1624     #[test]
ut_relation_set()1625     fn ut_relation_set() {
1626         unsafe {
1627             let temp = "temp";
1628             let set = OhCloudExtRelationSetNew(
1629                 temp.as_ptr() as *const c_uchar,
1630                 temp.len() as c_uint,
1631                 64,
1632                 null_mut(),
1633             );
1634             assert!(!set.is_null());
1635 
1636             let mut name: *mut c_uchar = null_mut();
1637             let mut length = 1 as c_uint;
1638             assert_eq!(
1639                 OhCloudExtRelationSetGetBundleName(
1640                     set,
1641                     &mut name as *mut _ as *mut *const c_uchar,
1642                     &mut length as *mut _ as *mut c_uint
1643                 ),
1644                 ERRNO_SUCCESS
1645             );
1646             let bundle_name = &*slice_from_raw_parts(name as *const u8, length as usize);
1647             assert_eq!(bundle_name, temp.as_bytes());
1648             assert_eq!(length as usize, temp.len());
1649             OhCloudExtRelationSetFree(set);
1650         }
1651     }
1652 }
1653