1dfe32fa1Soh_ci/* 2dfe32fa1Soh_ci * Copyright (c) 2023 Huawei Device Co., Ltd. 3dfe32fa1Soh_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4dfe32fa1Soh_ci * you may not use this file except in compliance with the License. 5dfe32fa1Soh_ci * You may obtain a copy of the License at 6dfe32fa1Soh_ci * 7dfe32fa1Soh_ci * http://www.apache.org/licenses/LICENSE-2.0 8dfe32fa1Soh_ci * 9dfe32fa1Soh_ci * Unless required by applicable law or agreed to in writing, software 10dfe32fa1Soh_ci * distributed under the License is distributed on an "AS IS" BASIS, 11dfe32fa1Soh_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12dfe32fa1Soh_ci * See the License for the specific language governing permissions and 13dfe32fa1Soh_ci * limitations under the License. 14dfe32fa1Soh_ci */ 15dfe32fa1Soh_ci 16dfe32fa1Soh_ci//! This module implements the function of Asset SDK from C to RUST. 17dfe32fa1Soh_ci 18dfe32fa1Soh_ciuse core::ffi::c_void; 19dfe32fa1Soh_ciuse std::{convert::TryFrom, mem::size_of, result::Result, slice}; 20dfe32fa1Soh_ci 21dfe32fa1Soh_ciuse asset_log::loge; 22dfe32fa1Soh_ciuse asset_sdk::{log_throw_error, AssetError, AssetMap, Conversion, DataType, ErrCode, Manager, Tag, Value}; 23dfe32fa1Soh_ci 24dfe32fa1Soh_ciconst MAX_MAP_CAPACITY: u32 = 64; 25dfe32fa1Soh_ciconst RESULT_CODE_SUCCESS: i32 = 0; 26dfe32fa1Soh_ciextern "C" { 27dfe32fa1Soh_ci fn AssetMalloc(size: u32) -> *mut c_void; 28dfe32fa1Soh_ci} 29dfe32fa1Soh_ci 30dfe32fa1Soh_cifn into_map(attributes: *const AssetAttr, attr_cnt: u32) -> Option<AssetMap> { 31dfe32fa1Soh_ci if attributes.is_null() && attr_cnt != 0 { 32dfe32fa1Soh_ci loge!("[FATAL][RUST SDK]Attributes is null."); 33dfe32fa1Soh_ci return None; 34dfe32fa1Soh_ci } 35dfe32fa1Soh_ci if attr_cnt > MAX_MAP_CAPACITY { 36dfe32fa1Soh_ci loge!("[FATAL][RUST SDK]Number of attributes exceeds limit."); 37dfe32fa1Soh_ci return None; 38dfe32fa1Soh_ci } 39dfe32fa1Soh_ci 40dfe32fa1Soh_ci let mut map = AssetMap::with_capacity(attr_cnt as usize); 41dfe32fa1Soh_ci for i in 0..attr_cnt { 42dfe32fa1Soh_ci unsafe { 43dfe32fa1Soh_ci let attr = attributes.add(i as usize); 44dfe32fa1Soh_ci let attr_tag = match Tag::try_from((*attr).tag) { 45dfe32fa1Soh_ci Ok(tag) => tag, 46dfe32fa1Soh_ci Err(_) => return None, 47dfe32fa1Soh_ci }; 48dfe32fa1Soh_ci match attr_tag.data_type() { 49dfe32fa1Soh_ci DataType::Bool => { 50dfe32fa1Soh_ci map.insert(attr_tag, Value::Bool((*attr).value.boolean)); 51dfe32fa1Soh_ci }, 52dfe32fa1Soh_ci DataType::Number => { 53dfe32fa1Soh_ci map.insert(attr_tag, Value::Number((*attr).value.uint32)); 54dfe32fa1Soh_ci }, 55dfe32fa1Soh_ci DataType::Bytes => { 56dfe32fa1Soh_ci if (*attr).value.blob.data.is_null() || (*attr).value.blob.size == 0 { 57dfe32fa1Soh_ci loge!("[FATAL][RUST SDK]Blob data is empty."); 58dfe32fa1Soh_ci return None; 59dfe32fa1Soh_ci } 60dfe32fa1Soh_ci let blob_slice = slice::from_raw_parts((*attr).value.blob.data, (*attr).value.blob.size as usize); 61dfe32fa1Soh_ci let blob_vec = blob_slice.to_vec(); 62dfe32fa1Soh_ci map.insert(attr_tag, Value::Bytes(blob_vec)); 63dfe32fa1Soh_ci }, 64dfe32fa1Soh_ci }; 65dfe32fa1Soh_ci } 66dfe32fa1Soh_ci } 67dfe32fa1Soh_ci Some(map) 68dfe32fa1Soh_ci} 69dfe32fa1Soh_ci 70dfe32fa1Soh_ci/// Function called from C programming language to Rust programming language for adding Asset. 71dfe32fa1Soh_ci#[no_mangle] 72dfe32fa1Soh_cipub extern "C" fn add_asset(attributes: *const AssetAttr, attr_cnt: u32) -> i32 { 73dfe32fa1Soh_ci let map = match into_map(attributes, attr_cnt) { 74dfe32fa1Soh_ci Some(map) => map, 75dfe32fa1Soh_ci None => return ErrCode::InvalidArgument as i32, 76dfe32fa1Soh_ci }; 77dfe32fa1Soh_ci 78dfe32fa1Soh_ci let manager = match Manager::build() { 79dfe32fa1Soh_ci Ok(manager) => manager, 80dfe32fa1Soh_ci Err(e) => return e.code as i32, 81dfe32fa1Soh_ci }; 82dfe32fa1Soh_ci 83dfe32fa1Soh_ci if let Err(e) = manager.add(&map) { 84dfe32fa1Soh_ci e.code as i32 85dfe32fa1Soh_ci } else { 86dfe32fa1Soh_ci RESULT_CODE_SUCCESS 87dfe32fa1Soh_ci } 88dfe32fa1Soh_ci} 89dfe32fa1Soh_ci 90dfe32fa1Soh_ci/// Function called from C programming language to Rust programming language for removing Asset. 91dfe32fa1Soh_ci#[no_mangle] 92dfe32fa1Soh_cipub extern "C" fn remove_asset(query: *const AssetAttr, query_cnt: u32) -> i32 { 93dfe32fa1Soh_ci let map = match into_map(query, query_cnt) { 94dfe32fa1Soh_ci Some(map) => map, 95dfe32fa1Soh_ci None => return ErrCode::InvalidArgument as i32, 96dfe32fa1Soh_ci }; 97dfe32fa1Soh_ci 98dfe32fa1Soh_ci let manager = match Manager::build() { 99dfe32fa1Soh_ci Ok(manager) => manager, 100dfe32fa1Soh_ci Err(e) => return e.code as i32, 101dfe32fa1Soh_ci }; 102dfe32fa1Soh_ci 103dfe32fa1Soh_ci if let Err(e) = manager.remove(&map) { 104dfe32fa1Soh_ci e.code as i32 105dfe32fa1Soh_ci } else { 106dfe32fa1Soh_ci RESULT_CODE_SUCCESS 107dfe32fa1Soh_ci } 108dfe32fa1Soh_ci} 109dfe32fa1Soh_ci 110dfe32fa1Soh_ci/// Function called from C programming language to Rust programming language for updating Asset. 111dfe32fa1Soh_ci#[no_mangle] 112dfe32fa1Soh_cipub extern "C" fn update_asset( 113dfe32fa1Soh_ci query: *const AssetAttr, 114dfe32fa1Soh_ci query_cnt: u32, 115dfe32fa1Soh_ci attrs_to_update: *const AssetAttr, 116dfe32fa1Soh_ci update_cnt: u32, 117dfe32fa1Soh_ci) -> i32 { 118dfe32fa1Soh_ci let query_map = match into_map(query, query_cnt) { 119dfe32fa1Soh_ci Some(map) => map, 120dfe32fa1Soh_ci None => return ErrCode::InvalidArgument as i32, 121dfe32fa1Soh_ci }; 122dfe32fa1Soh_ci 123dfe32fa1Soh_ci let update_map = match into_map(attrs_to_update, update_cnt) { 124dfe32fa1Soh_ci Some(map) => map, 125dfe32fa1Soh_ci None => return ErrCode::InvalidArgument as i32, 126dfe32fa1Soh_ci }; 127dfe32fa1Soh_ci 128dfe32fa1Soh_ci let manager = match Manager::build() { 129dfe32fa1Soh_ci Ok(manager) => manager, 130dfe32fa1Soh_ci Err(e) => return e.code as i32, 131dfe32fa1Soh_ci }; 132dfe32fa1Soh_ci 133dfe32fa1Soh_ci if let Err(e) = manager.update(&query_map, &update_map) { 134dfe32fa1Soh_ci e.code as i32 135dfe32fa1Soh_ci } else { 136dfe32fa1Soh_ci RESULT_CODE_SUCCESS 137dfe32fa1Soh_ci } 138dfe32fa1Soh_ci} 139dfe32fa1Soh_ci 140dfe32fa1Soh_ci/// Function called from C programming language to Rust programming language for pre querying Asset. 141dfe32fa1Soh_ci/// 142dfe32fa1Soh_ci/// # Safety 143dfe32fa1Soh_ci/// 144dfe32fa1Soh_ci/// The caller must ensure that the challenge pointer is valid. 145dfe32fa1Soh_ci#[no_mangle] 146dfe32fa1Soh_cipub unsafe extern "C" fn pre_query_asset(query: *const AssetAttr, query_cnt: u32, challenge: *mut AssetBlob) -> i32 { 147dfe32fa1Soh_ci let map = match into_map(query, query_cnt) { 148dfe32fa1Soh_ci Some(map) => map, 149dfe32fa1Soh_ci None => return ErrCode::InvalidArgument as i32, 150dfe32fa1Soh_ci }; 151dfe32fa1Soh_ci 152dfe32fa1Soh_ci if challenge.is_null() { 153dfe32fa1Soh_ci loge!("[FATAL][RUST SDK]challenge is null"); 154dfe32fa1Soh_ci return ErrCode::InvalidArgument as i32; 155dfe32fa1Soh_ci } 156dfe32fa1Soh_ci 157dfe32fa1Soh_ci let manager = match Manager::build() { 158dfe32fa1Soh_ci Ok(manager) => manager, 159dfe32fa1Soh_ci Err(e) => return e.code as i32, 160dfe32fa1Soh_ci }; 161dfe32fa1Soh_ci 162dfe32fa1Soh_ci let res = match manager.pre_query(&map) { 163dfe32fa1Soh_ci Err(e) => return e.code as i32, 164dfe32fa1Soh_ci Ok(res) => res, 165dfe32fa1Soh_ci }; 166dfe32fa1Soh_ci 167dfe32fa1Soh_ci match AssetBlob::try_from(&res) { 168dfe32fa1Soh_ci Err(e) => e.code as i32, 169dfe32fa1Soh_ci Ok(b) => { 170dfe32fa1Soh_ci *challenge = b; 171dfe32fa1Soh_ci RESULT_CODE_SUCCESS 172dfe32fa1Soh_ci }, 173dfe32fa1Soh_ci } 174dfe32fa1Soh_ci} 175dfe32fa1Soh_ci 176dfe32fa1Soh_ci/// Function called from C programming language to Rust programming language for querying Asset. 177dfe32fa1Soh_ci/// 178dfe32fa1Soh_ci/// # Safety 179dfe32fa1Soh_ci/// 180dfe32fa1Soh_ci/// The caller must ensure that the result_set pointer is valid. 181dfe32fa1Soh_ci#[no_mangle] 182dfe32fa1Soh_cipub unsafe extern "C" fn query_asset(query: *const AssetAttr, query_cnt: u32, result_set: *mut AssetResultSet) -> i32 { 183dfe32fa1Soh_ci let map = match into_map(query, query_cnt) { 184dfe32fa1Soh_ci Some(map) => map, 185dfe32fa1Soh_ci None => return ErrCode::InvalidArgument as i32, 186dfe32fa1Soh_ci }; 187dfe32fa1Soh_ci 188dfe32fa1Soh_ci if result_set.is_null() { 189dfe32fa1Soh_ci loge!("[FATAL][RUST SDK]result set is null"); 190dfe32fa1Soh_ci return ErrCode::InvalidArgument as i32; 191dfe32fa1Soh_ci } 192dfe32fa1Soh_ci 193dfe32fa1Soh_ci let manager = match Manager::build() { 194dfe32fa1Soh_ci Ok(manager) => manager, 195dfe32fa1Soh_ci Err(e) => return e.code as i32, 196dfe32fa1Soh_ci }; 197dfe32fa1Soh_ci 198dfe32fa1Soh_ci let res = match manager.query(&map) { 199dfe32fa1Soh_ci Err(e) => return e.code as i32, 200dfe32fa1Soh_ci Ok(res) => res, 201dfe32fa1Soh_ci }; 202dfe32fa1Soh_ci 203dfe32fa1Soh_ci match AssetResultSet::try_from(&res) { 204dfe32fa1Soh_ci Err(e) => e.code as i32, 205dfe32fa1Soh_ci Ok(s) => { 206dfe32fa1Soh_ci *result_set = s; 207dfe32fa1Soh_ci RESULT_CODE_SUCCESS 208dfe32fa1Soh_ci }, 209dfe32fa1Soh_ci } 210dfe32fa1Soh_ci} 211dfe32fa1Soh_ci 212dfe32fa1Soh_ci/// Function called from C programming language to Rust programming language for post quering Asset. 213dfe32fa1Soh_ci#[no_mangle] 214dfe32fa1Soh_cipub extern "C" fn post_query_asset(handle: *const AssetAttr, handle_cnt: u32) -> i32 { 215dfe32fa1Soh_ci let map = match into_map(handle, handle_cnt) { 216dfe32fa1Soh_ci Some(map) => map, 217dfe32fa1Soh_ci None => return ErrCode::InvalidArgument as i32, 218dfe32fa1Soh_ci }; 219dfe32fa1Soh_ci 220dfe32fa1Soh_ci let manager = match Manager::build() { 221dfe32fa1Soh_ci Ok(manager) => manager, 222dfe32fa1Soh_ci Err(e) => return e.code as i32, 223dfe32fa1Soh_ci }; 224dfe32fa1Soh_ci 225dfe32fa1Soh_ci if let Err(e) = manager.post_query(&map) { 226dfe32fa1Soh_ci e.code as i32 227dfe32fa1Soh_ci } else { 228dfe32fa1Soh_ci RESULT_CODE_SUCCESS 229dfe32fa1Soh_ci } 230dfe32fa1Soh_ci} 231dfe32fa1Soh_ci 232dfe32fa1Soh_ci/// Attribute of Asset with a c representation. 233dfe32fa1Soh_ci#[repr(C)] 234dfe32fa1Soh_cipub struct AssetAttr { 235dfe32fa1Soh_ci tag: u32, 236dfe32fa1Soh_ci value: AssetValue, 237dfe32fa1Soh_ci} 238dfe32fa1Soh_ci 239dfe32fa1Soh_ci/// Blob of Asset with a c representation. 240dfe32fa1Soh_ci#[repr(C)] 241dfe32fa1Soh_ci#[derive(Clone, Copy)] 242dfe32fa1Soh_cipub struct AssetBlob { 243dfe32fa1Soh_ci size: u32, 244dfe32fa1Soh_ci data: *mut u8, 245dfe32fa1Soh_ci} 246dfe32fa1Soh_ci 247dfe32fa1Soh_ciimpl TryFrom<&Vec<u8>> for AssetBlob { 248dfe32fa1Soh_ci type Error = AssetError; 249dfe32fa1Soh_ci 250dfe32fa1Soh_ci fn try_from(vec: &Vec<u8>) -> Result<Self, Self::Error> { 251dfe32fa1Soh_ci let mut blob = AssetBlob { size: vec.len() as u32, data: std::ptr::null_mut() }; 252dfe32fa1Soh_ci 253dfe32fa1Soh_ci blob.data = unsafe { AssetMalloc(blob.size) as *mut u8 }; 254dfe32fa1Soh_ci if blob.data.is_null() { 255dfe32fa1Soh_ci return log_throw_error!( 256dfe32fa1Soh_ci ErrCode::OutOfMemory, 257dfe32fa1Soh_ci "[FATAL][RUST SDK]Unable to allocate memory for Asset_Blob." 258dfe32fa1Soh_ci ); 259dfe32fa1Soh_ci } 260dfe32fa1Soh_ci unsafe { std::ptr::copy_nonoverlapping(vec.as_ptr(), blob.data, blob.size as usize) }; 261dfe32fa1Soh_ci Ok(blob) 262dfe32fa1Soh_ci } 263dfe32fa1Soh_ci} 264dfe32fa1Soh_ci 265dfe32fa1Soh_ci#[repr(C)] 266dfe32fa1Soh_ciunion AssetValue { 267dfe32fa1Soh_ci boolean: bool, 268dfe32fa1Soh_ci uint32: u32, 269dfe32fa1Soh_ci blob: AssetBlob, 270dfe32fa1Soh_ci} 271dfe32fa1Soh_ci 272dfe32fa1Soh_ciimpl TryFrom<&Value> for AssetValue { 273dfe32fa1Soh_ci type Error = AssetError; 274dfe32fa1Soh_ci 275dfe32fa1Soh_ci fn try_from(value: &Value) -> Result<Self, Self::Error> { 276dfe32fa1Soh_ci let mut out = AssetValue { boolean: false }; 277dfe32fa1Soh_ci match value { 278dfe32fa1Soh_ci Value::Bool(v) => out.boolean = *v, 279dfe32fa1Soh_ci Value::Number(v) => out.uint32 = *v, 280dfe32fa1Soh_ci Value::Bytes(v) => out.blob = AssetBlob::try_from(v)?, 281dfe32fa1Soh_ci } 282dfe32fa1Soh_ci Ok(out) 283dfe32fa1Soh_ci } 284dfe32fa1Soh_ci} 285dfe32fa1Soh_ci 286dfe32fa1Soh_ci#[repr(C)] 287dfe32fa1Soh_cistruct AssetResult { 288dfe32fa1Soh_ci count: u32, 289dfe32fa1Soh_ci attrs: *mut AssetAttr, 290dfe32fa1Soh_ci} 291dfe32fa1Soh_ci 292dfe32fa1Soh_ciimpl TryFrom<&AssetMap> for AssetResult { 293dfe32fa1Soh_ci type Error = AssetError; 294dfe32fa1Soh_ci 295dfe32fa1Soh_ci fn try_from(map: &AssetMap) -> Result<Self, Self::Error> { 296dfe32fa1Soh_ci let mut result = AssetResult { count: map.len() as u32, attrs: std::ptr::null_mut() }; 297dfe32fa1Soh_ci 298dfe32fa1Soh_ci result.attrs = 299dfe32fa1Soh_ci unsafe { AssetMalloc(result.count.wrapping_mul(size_of::<AssetAttr>() as u32)) as *mut AssetAttr }; 300dfe32fa1Soh_ci if result.attrs.is_null() { 301dfe32fa1Soh_ci return log_throw_error!( 302dfe32fa1Soh_ci ErrCode::OutOfMemory, 303dfe32fa1Soh_ci "[FATAL][RUST SDK]Unable to allocate memory for Asset_Result." 304dfe32fa1Soh_ci ); 305dfe32fa1Soh_ci } 306dfe32fa1Soh_ci 307dfe32fa1Soh_ci for (i, (tag, value)) in map.iter().enumerate() { 308dfe32fa1Soh_ci unsafe { 309dfe32fa1Soh_ci let attr = result.attrs.add(i); 310dfe32fa1Soh_ci (*attr).tag = *tag as u32; 311dfe32fa1Soh_ci (*attr).value = AssetValue::try_from(value)?; 312dfe32fa1Soh_ci } 313dfe32fa1Soh_ci } 314dfe32fa1Soh_ci Ok(result) 315dfe32fa1Soh_ci } 316dfe32fa1Soh_ci} 317dfe32fa1Soh_ci 318dfe32fa1Soh_ci/// ResultSet of Asset with a c representation. 319dfe32fa1Soh_ci#[repr(C)] 320dfe32fa1Soh_cipub struct AssetResultSet { 321dfe32fa1Soh_ci count: u32, 322dfe32fa1Soh_ci results: *mut AssetResult, 323dfe32fa1Soh_ci} 324dfe32fa1Soh_ci 325dfe32fa1Soh_ciimpl TryFrom<&Vec<AssetMap>> for AssetResultSet { 326dfe32fa1Soh_ci type Error = AssetError; 327dfe32fa1Soh_ci 328dfe32fa1Soh_ci fn try_from(maps: &Vec<AssetMap>) -> Result<Self, Self::Error> { 329dfe32fa1Soh_ci let mut result_set = AssetResultSet { count: maps.len() as u32, results: std::ptr::null_mut() }; 330dfe32fa1Soh_ci result_set.results = 331dfe32fa1Soh_ci unsafe { AssetMalloc(result_set.count.wrapping_mul(size_of::<AssetResult>() as u32)) as *mut AssetResult }; 332dfe32fa1Soh_ci if result_set.results.is_null() { 333dfe32fa1Soh_ci return log_throw_error!( 334dfe32fa1Soh_ci ErrCode::OutOfMemory, 335dfe32fa1Soh_ci "[FATAL][RUST SDK]Unable to allocate memory for Asset_ResultSet." 336dfe32fa1Soh_ci ); 337dfe32fa1Soh_ci } 338dfe32fa1Soh_ci for (i, map) in maps.iter().enumerate() { 339dfe32fa1Soh_ci unsafe { 340dfe32fa1Soh_ci let result = result_set.results.add(i); 341dfe32fa1Soh_ci *result = AssetResult::try_from(map)?; 342dfe32fa1Soh_ci } 343dfe32fa1Soh_ci } 344dfe32fa1Soh_ci Ok(result_set) 345dfe32fa1Soh_ci } 346dfe32fa1Soh_ci} 347