* Copyright (c) 2023-2025 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
use ipc::{parcel::{MsgParcel, Deserialize}, IpcStatusCode};
use asset_definition::{
macros_lib, AssetError, AssetMap, Conversion, DataType, ErrCode, Result, SyncResult, Tag, Value
};
pub const SA_ID: i32 = 8100;
pub const SA_NAME: &str = "security_asset_service";
pub const IPC_SUCCESS: u32 = 0;
const MAX_MAP_CAPACITY: u32 = 64;
const MAX_VEC_CAPACITY: u32 = 0x10000;
const MAX_ATTR_ARRAY_CAPACITY: u32 = 100;
macros_lib::impl_enum_trait! {
#[derive(Clone, Copy)]
#[derive(Eq, PartialEq)]
pub enum IpcCode {
Add = ipc::FIRST_CALL_TRANSACTION,
Remove,
Update,
PreQuery,
Query,
PostQuery,
QuerySyncResult,
BatchAdd,
BatchRemove,
BatchUpdate,
}
}
pub fn deserialize<T: Deserialize>(parcel: &mut MsgParcel) -> Result<T> {
let value = parcel.read::<T>()
.map_err(|_| macros_lib::log_and_into_asset_error!(macros_lib::hisysevent::function!(),
ErrCode::InvalidArgument, "[FATAL]deserialize T from parcel failed!" ))?;
Ok(value)
}
pub fn serialize_map(map: &AssetMap, parcel: &mut MsgParcel) -> Result<()> {
if map.len() as u32 > MAX_MAP_CAPACITY {
return macros_lib::log_throw_error!(macros_lib::hisysevent::function!(),
ErrCode::InvalidArgument, "[FATAL][IPC]The map size exceeds the limit.");
}
parcel.write(&(map.len() as u32)).map_err(ipc_err_handle)?;
for (&tag, value) in map.iter() {
if tag.data_type() != value.data_type() {
return macros_lib::log_throw_error!(macros_lib::hisysevent::function!(),
ErrCode::InvalidArgument,
"[FATAL][IPC]Data type mismatch, key type: {}, value type: {}", tag.data_type(), value.data_type() );
}
parcel.write(&(tag as u32)).map_err(ipc_err_handle)?;
match value {
Value::Bool(b) => parcel.write::<bool>(b).map_err(ipc_err_handle)?,
Value::Number(n) => parcel.write::<u32>(n).map_err(ipc_err_handle)?,
Value::Bytes(a) => parcel.write::<Vec<u8>>(a).map_err(ipc_err_handle)?,
}
}
Ok(())
}
pub fn deserialize_map(parcel: &mut MsgParcel) -> Result<AssetMap> {
let len = parcel.read::<u32>().map_err(ipc_err_handle)?;
if len > MAX_MAP_CAPACITY {
return macros_lib::log_throw_error!(macros_lib::hisysevent::function!(),
ErrCode::InvalidArgument, "[FATAL][IPC]The map size exceeds the limit.");
}
let mut map = AssetMap::with_capacity(len as usize);
for _ in 0..len {
let tag = parcel.read::<u32>().map_err(ipc_err_handle)?;
let tag = Tag::try_from(tag)?;
match tag.data_type() {
DataType::Bool => {
let v = parcel.read::<bool>().map_err(ipc_err_handle)?;
map.insert(tag, Value::Bool(v));
},
DataType::Number => {
let v = parcel.read::<u32>().map_err(ipc_err_handle)?;
map.insert(tag, Value::Number(v));
},
DataType::Bytes => {
let v = parcel.read::<Vec<u8>>().map_err(ipc_err_handle)?;
map.insert(tag, Value::Bytes(v));
},
}
}
Ok(map)
}
pub fn serialize_maps(vec: &Vec<AssetMap>, parcel: &mut MsgParcel) -> Result<()> {
if vec.len() as u32 > MAX_VEC_CAPACITY {
return macros_lib::log_throw_error!(macros_lib::hisysevent::function!(),
ErrCode::InvalidArgument, "[FATAL][IPC]The vector size exceeds the limit.");
}
parcel.write::<u32>(&(vec.len() as u32)).map_err(ipc_err_handle)?;
for map in vec.iter() {
serialize_map(map, parcel)?;
}
Ok(())
}
pub fn deserialize_maps(parcel: &mut MsgParcel) -> Result<Vec<AssetMap>> {
let len = parcel.read::<u32>().map_err(ipc_err_handle)?;
if len > MAX_VEC_CAPACITY {
return macros_lib::log_throw_error!(macros_lib::hisysevent::function!(),
ErrCode::InvalidArgument, "[FATAL][IPC]The vector size exceeds the limit.");
}
let mut res_vec = Vec::with_capacity(len as usize);
for _i in 0..len {
res_vec.push(deserialize_map(parcel)?);
}
Ok(res_vec)
}
pub fn serialize_sync_result(sync_result: &SyncResult, parcel: &mut MsgParcel) -> Result<()> {
parcel.write::<i32>(&sync_result.result_code).map_err(ipc_err_handle)?;
parcel.write::<u32>(&sync_result.total_count).map_err(ipc_err_handle)?;
parcel.write::<u32>(&sync_result.failed_count).map_err(ipc_err_handle)
}
pub fn deserialize_sync_result(parcel: &mut MsgParcel) -> Result<SyncResult> {
Ok(SyncResult {
result_code: parcel.read::<i32>().map_err(ipc_err_handle)?,
total_count: parcel.read::<u32>().map_err(ipc_err_handle)?,
failed_count: parcel.read::<u32>().map_err(ipc_err_handle)?,
})
}
pub fn serialize_batch_result(result: &Vec<(u32, u32)>, parcel: &mut MsgParcel) -> Result<()> {
if result.len() as u32 > MAX_ATTR_ARRAY_CAPACITY {
return macros_lib::log_throw_error!(macros_lib::hisysevent::function!(),
ErrCode::InvalidArgument, "[FATAL][IPC]The result size exceeds the limit." );
}
parcel.write::<u32>(&(result.len() as u32)).map_err(ipc_err_handle)?;
for (index, error_code) in result.iter() {
parcel.write::<u32>(index).map_err(ipc_err_handle)?;
parcel.write::<u32>(error_code).map_err(ipc_err_handle)?;
}
Ok(())
}
pub fn deserialize_batch_result(parcel: &mut MsgParcel) -> Result<Vec<(u32, u32)>> {
let len = parcel.read::<u32>().map_err(ipc_err_handle)?;
if len > MAX_ATTR_ARRAY_CAPACITY {
return macros_lib::log_throw_error!(macros_lib::hisysevent::function!(),
ErrCode::InvalidArgument, "[FATAL][IPC]The result size exceeds the limit." );
}
let mut res_vec = Vec::with_capacity(len as usize);
for _i in 0..len {
let index = parcel.read::<u32>().map_err(ipc_err_handle)?;
let error_code = parcel.read::<u32>().map_err(ipc_err_handle)?;
res_vec.push((index, error_code));
}
Ok(res_vec)
}
pub fn ipc_err_handle(e: IpcStatusCode) -> AssetError {
match e {
IpcStatusCode::ServiceDied => {
AssetError::new(ErrCode::ServiceUnavailable, format!("[FATAL][IPC]Ipc status code = {}", e as i32), macros_lib::hisysevent::function!())
},
_ => AssetError::new(ErrCode::IpcError, format!("[FATAL][IPC]Ipc status code = {}", e), macros_lib::hisysevent::function!()),
}
}