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 defines IPC interfaces and constants.
17dfe32fa1Soh_ci
18dfe32fa1Soh_ciuse ipc::{parcel::MsgParcel, IpcStatusCode};
19dfe32fa1Soh_ci
20dfe32fa1Soh_ciuse asset_definition::{
21dfe32fa1Soh_ci    impl_enum_trait, log_throw_error, AssetError, AssetMap, Conversion, DataType, ErrCode, Result, Tag, Value,
22dfe32fa1Soh_ci};
23dfe32fa1Soh_ci
24dfe32fa1Soh_ci/// SA id for Asset service.
25dfe32fa1Soh_cipub const SA_ID: i32 = 8100;
26dfe32fa1Soh_ci/// SA name for Asset service.
27dfe32fa1Soh_cipub const SA_NAME: &str = "security_asset_service";
28dfe32fa1Soh_ci/// IPC result code.
29dfe32fa1Soh_cipub const IPC_SUCCESS: u32 = 0;
30dfe32fa1Soh_ci
31dfe32fa1Soh_ciconst MAX_MAP_CAPACITY: u32 = 64;
32dfe32fa1Soh_ciconst MAX_VEC_CAPACITY: u32 = 0x10000;
33dfe32fa1Soh_ci
34dfe32fa1Soh_ciimpl_enum_trait! {
35dfe32fa1Soh_ci    /// Code used to identify the function to be called.
36dfe32fa1Soh_ci    #[derive(Clone, Copy)]
37dfe32fa1Soh_ci    #[derive(Eq, PartialEq)]
38dfe32fa1Soh_ci    pub enum IpcCode {
39dfe32fa1Soh_ci        /// Code for AddAsset.
40dfe32fa1Soh_ci        Add = ipc::FIRST_CALL_TRANSACTION,
41dfe32fa1Soh_ci        /// Code for RemoveAsset.
42dfe32fa1Soh_ci        Remove,
43dfe32fa1Soh_ci        /// Code for UpdateAsset.
44dfe32fa1Soh_ci        Update,
45dfe32fa1Soh_ci        /// Code for PreQueryAsset.
46dfe32fa1Soh_ci        PreQuery,
47dfe32fa1Soh_ci        /// Code for QueryAsset.
48dfe32fa1Soh_ci        Query,
49dfe32fa1Soh_ci        /// Code for PostQueryAsset.
50dfe32fa1Soh_ci        PostQuery,
51dfe32fa1Soh_ci    }
52dfe32fa1Soh_ci}
53dfe32fa1Soh_ci
54dfe32fa1Soh_ci/// serialize the map to parcel
55dfe32fa1Soh_cipub fn serialize_map(map: &AssetMap, parcel: &mut MsgParcel) -> Result<()> {
56dfe32fa1Soh_ci    if map.len() as u32 > MAX_MAP_CAPACITY {
57dfe32fa1Soh_ci        return log_throw_error!(ErrCode::InvalidArgument, "[FALTAL][IPC]The map size exceeds the limit.");
58dfe32fa1Soh_ci    }
59dfe32fa1Soh_ci    parcel.write(&(map.len() as u32)).map_err(ipc_err_handle)?;
60dfe32fa1Soh_ci    for (&tag, value) in map.iter() {
61dfe32fa1Soh_ci        if tag.data_type() != value.data_type() {
62dfe32fa1Soh_ci            return log_throw_error!(
63dfe32fa1Soh_ci                ErrCode::InvalidArgument,
64dfe32fa1Soh_ci                "[FATAL][IPC]Data type mismatch, key type: {}, value type: {}",
65dfe32fa1Soh_ci                tag.data_type(),
66dfe32fa1Soh_ci                value.data_type()
67dfe32fa1Soh_ci            );
68dfe32fa1Soh_ci        }
69dfe32fa1Soh_ci        parcel.write(&(tag as u32)).map_err(ipc_err_handle)?;
70dfe32fa1Soh_ci        match value {
71dfe32fa1Soh_ci            Value::Bool(b) => parcel.write::<bool>(b).map_err(ipc_err_handle)?,
72dfe32fa1Soh_ci            Value::Number(n) => parcel.write::<u32>(n).map_err(ipc_err_handle)?,
73dfe32fa1Soh_ci            Value::Bytes(a) => parcel.write::<Vec<u8>>(a).map_err(ipc_err_handle)?,
74dfe32fa1Soh_ci        }
75dfe32fa1Soh_ci    }
76dfe32fa1Soh_ci    Ok(())
77dfe32fa1Soh_ci}
78dfe32fa1Soh_ci
79dfe32fa1Soh_ci/// deserialize the map from parcel
80dfe32fa1Soh_cipub fn deserialize_map(parcel: &mut MsgParcel) -> Result<AssetMap> {
81dfe32fa1Soh_ci    let len = parcel.read::<u32>().map_err(ipc_err_handle)?;
82dfe32fa1Soh_ci    if len > MAX_MAP_CAPACITY {
83dfe32fa1Soh_ci        return log_throw_error!(ErrCode::InvalidArgument, "[FATAL][IPC]The map size exceeds the limit.");
84dfe32fa1Soh_ci    }
85dfe32fa1Soh_ci    let mut map = AssetMap::with_capacity(len as usize);
86dfe32fa1Soh_ci    for _ in 0..len {
87dfe32fa1Soh_ci        let tag = parcel.read::<u32>().map_err(ipc_err_handle)?;
88dfe32fa1Soh_ci        let tag = Tag::try_from(tag)?;
89dfe32fa1Soh_ci        match tag.data_type() {
90dfe32fa1Soh_ci            DataType::Bool => {
91dfe32fa1Soh_ci                let v = parcel.read::<bool>().map_err(ipc_err_handle)?;
92dfe32fa1Soh_ci                map.insert(tag, Value::Bool(v));
93dfe32fa1Soh_ci            },
94dfe32fa1Soh_ci            DataType::Number => {
95dfe32fa1Soh_ci                let v = parcel.read::<u32>().map_err(ipc_err_handle)?;
96dfe32fa1Soh_ci                map.insert(tag, Value::Number(v));
97dfe32fa1Soh_ci            },
98dfe32fa1Soh_ci            DataType::Bytes => {
99dfe32fa1Soh_ci                let v = parcel.read::<Vec<u8>>().map_err(ipc_err_handle)?;
100dfe32fa1Soh_ci                map.insert(tag, Value::Bytes(v));
101dfe32fa1Soh_ci            },
102dfe32fa1Soh_ci        }
103dfe32fa1Soh_ci    }
104dfe32fa1Soh_ci    Ok(map)
105dfe32fa1Soh_ci}
106dfe32fa1Soh_ci
107dfe32fa1Soh_ci/// Serialize the collection of map to parcel.
108dfe32fa1Soh_cipub fn serialize_maps(vec: &Vec<AssetMap>, parcel: &mut MsgParcel) -> Result<()> {
109dfe32fa1Soh_ci    if vec.len() as u32 > MAX_VEC_CAPACITY {
110dfe32fa1Soh_ci        return log_throw_error!(ErrCode::InvalidArgument, "[FATAL][IPC]The vector size exceeds the limit.");
111dfe32fa1Soh_ci    }
112dfe32fa1Soh_ci    parcel.write::<u32>(&(vec.len() as u32)).map_err(ipc_err_handle)?;
113dfe32fa1Soh_ci    for map in vec.iter() {
114dfe32fa1Soh_ci        serialize_map(map, parcel)?;
115dfe32fa1Soh_ci    }
116dfe32fa1Soh_ci    Ok(())
117dfe32fa1Soh_ci}
118dfe32fa1Soh_ci
119dfe32fa1Soh_ci/// Deserialize the collection of map from parcel.
120dfe32fa1Soh_cipub fn deserialize_maps(parcel: &mut MsgParcel) -> Result<Vec<AssetMap>> {
121dfe32fa1Soh_ci    let len = parcel.read::<u32>().map_err(ipc_err_handle)?;
122dfe32fa1Soh_ci    if len > MAX_VEC_CAPACITY {
123dfe32fa1Soh_ci        return log_throw_error!(ErrCode::InvalidArgument, "[FATAL][IPC]The vector size exceeds the limit.");
124dfe32fa1Soh_ci    }
125dfe32fa1Soh_ci    let mut res_vec = Vec::with_capacity(len as usize);
126dfe32fa1Soh_ci    for _i in 0..len {
127dfe32fa1Soh_ci        res_vec.push(deserialize_map(parcel)?);
128dfe32fa1Soh_ci    }
129dfe32fa1Soh_ci    Ok(res_vec)
130dfe32fa1Soh_ci}
131dfe32fa1Soh_ci
132dfe32fa1Soh_ci/// Convert ipc error into Asset error.
133dfe32fa1Soh_cipub fn ipc_err_handle(e: IpcStatusCode) -> AssetError {
134dfe32fa1Soh_ci    AssetError::new(ErrCode::IpcError, format!("[FATAL][IPC]Ipc status code = {}", e))
135dfe32fa1Soh_ci}
136