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 extends the function of Asset data structure.
17dfe32fa1Soh_ci
18dfe32fa1Soh_ciuse std::{collections::HashMap, fmt::Display, hash::Hash, io};
19dfe32fa1Soh_ci
20dfe32fa1Soh_ciuse asset_log::loge;
21dfe32fa1Soh_ci
22dfe32fa1Soh_ciuse super::{
23dfe32fa1Soh_ci    impl_from_for_u32, log_throw_error, Accessibility, AssetError, AuthType, Conversion, DataType, ErrCode, Extension,
24dfe32fa1Soh_ci    Result, Tag, Value,
25dfe32fa1Soh_ci};
26dfe32fa1Soh_ci
27dfe32fa1Soh_ci/// The mask used to obtain the data type of Asset attribute value.
28dfe32fa1Soh_ciconst DATA_TYPE_MASK: u32 = 0xF << 28;
29dfe32fa1Soh_ci
30dfe32fa1Soh_ciimpl Conversion for Tag {
31dfe32fa1Soh_ci    fn data_type(&self) -> DataType {
32dfe32fa1Soh_ci        let mask = (*self as u32) & DATA_TYPE_MASK;
33dfe32fa1Soh_ci        match mask {
34dfe32fa1Soh_ci            _ if DataType::Bool as u32 == mask => DataType::Bool,
35dfe32fa1Soh_ci            _ if DataType::Number as u32 == mask => DataType::Number,
36dfe32fa1Soh_ci            _ if DataType::Bytes as u32 == mask => DataType::Bytes,
37dfe32fa1Soh_ci            _ => {
38dfe32fa1Soh_ci                panic!("Unexpected data type, it should be bool, uint32 or bytes.");
39dfe32fa1Soh_ci            },
40dfe32fa1Soh_ci        }
41dfe32fa1Soh_ci    }
42dfe32fa1Soh_ci
43dfe32fa1Soh_ci    fn into_value(self) -> Value {
44dfe32fa1Soh_ci        Value::Number(self as u32)
45dfe32fa1Soh_ci    }
46dfe32fa1Soh_ci}
47dfe32fa1Soh_ci
48dfe32fa1Soh_ciimpl Conversion for Value {
49dfe32fa1Soh_ci    fn data_type(&self) -> DataType {
50dfe32fa1Soh_ci        match self {
51dfe32fa1Soh_ci            Value::Bool(_) => DataType::Bool,
52dfe32fa1Soh_ci            Value::Number(_) => DataType::Number,
53dfe32fa1Soh_ci            Value::Bytes(_) => DataType::Bytes,
54dfe32fa1Soh_ci        }
55dfe32fa1Soh_ci    }
56dfe32fa1Soh_ci
57dfe32fa1Soh_ci    fn into_value(self) -> Value {
58dfe32fa1Soh_ci        self
59dfe32fa1Soh_ci    }
60dfe32fa1Soh_ci}
61dfe32fa1Soh_ci
62dfe32fa1Soh_ciimpl Conversion for Vec<u8> {
63dfe32fa1Soh_ci    fn data_type(&self) -> DataType {
64dfe32fa1Soh_ci        DataType::Bytes
65dfe32fa1Soh_ci    }
66dfe32fa1Soh_ci
67dfe32fa1Soh_ci    fn into_value(self) -> Value {
68dfe32fa1Soh_ci        Value::Bytes(self)
69dfe32fa1Soh_ci    }
70dfe32fa1Soh_ci}
71dfe32fa1Soh_ci
72dfe32fa1Soh_ciimpl Conversion for bool {
73dfe32fa1Soh_ci    fn data_type(&self) -> DataType {
74dfe32fa1Soh_ci        DataType::Bool
75dfe32fa1Soh_ci    }
76dfe32fa1Soh_ci
77dfe32fa1Soh_ci    fn into_value(self) -> Value {
78dfe32fa1Soh_ci        Value::Bool(self)
79dfe32fa1Soh_ci    }
80dfe32fa1Soh_ci}
81dfe32fa1Soh_ci
82dfe32fa1Soh_ciimpl Conversion for u32 {
83dfe32fa1Soh_ci    fn data_type(&self) -> DataType {
84dfe32fa1Soh_ci        DataType::Number
85dfe32fa1Soh_ci    }
86dfe32fa1Soh_ci
87dfe32fa1Soh_ci    fn into_value(self) -> Value {
88dfe32fa1Soh_ci        Value::Number(self)
89dfe32fa1Soh_ci    }
90dfe32fa1Soh_ci}
91dfe32fa1Soh_ci
92dfe32fa1Soh_ciimpl<K> Extension<K> for HashMap<K, Value>
93dfe32fa1Soh_ciwhere
94dfe32fa1Soh_ci    K: Eq + PartialEq + Hash + std::fmt::Display,
95dfe32fa1Soh_ci{
96dfe32fa1Soh_ci    fn insert_attr(&mut self, key: K, value: impl Conversion) {
97dfe32fa1Soh_ci        self.insert(key, value.into_value());
98dfe32fa1Soh_ci    }
99dfe32fa1Soh_ci
100dfe32fa1Soh_ci    fn get_bool_attr(&self, key: &K) -> Result<bool> {
101dfe32fa1Soh_ci        if let Some(Value::Bool(b)) = self.get(key) {
102dfe32fa1Soh_ci            Ok(*b)
103dfe32fa1Soh_ci        } else {
104dfe32fa1Soh_ci            log_throw_error!(ErrCode::InvalidArgument, "[FATAL]Get attribute of bool type failed, key: {}", key)
105dfe32fa1Soh_ci        }
106dfe32fa1Soh_ci    }
107dfe32fa1Soh_ci
108dfe32fa1Soh_ci    fn get_enum_attr<T: TryFrom<u32, Error = AssetError>>(&self, key: &K) -> Result<T> {
109dfe32fa1Soh_ci        if let Some(Value::Number(num)) = self.get(key) {
110dfe32fa1Soh_ci            T::try_from(*num)
111dfe32fa1Soh_ci        } else {
112dfe32fa1Soh_ci            log_throw_error!(ErrCode::InvalidArgument, "[FATAL]Get attribute of enum type failed, key: {}", key)
113dfe32fa1Soh_ci        }
114dfe32fa1Soh_ci    }
115dfe32fa1Soh_ci
116dfe32fa1Soh_ci    fn get_num_attr(&self, key: &K) -> Result<u32> {
117dfe32fa1Soh_ci        if let Some(Value::Number(num)) = self.get(key) {
118dfe32fa1Soh_ci            Ok(*num)
119dfe32fa1Soh_ci        } else {
120dfe32fa1Soh_ci            log_throw_error!(ErrCode::InvalidArgument, "[FATAL]Get attribute of number type failed, key: {}", key)
121dfe32fa1Soh_ci        }
122dfe32fa1Soh_ci    }
123dfe32fa1Soh_ci
124dfe32fa1Soh_ci    fn get_bytes_attr(&self, key: &K) -> Result<&Vec<u8>> {
125dfe32fa1Soh_ci        if let Some(Value::Bytes(bytes)) = self.get(key) {
126dfe32fa1Soh_ci            Ok(bytes)
127dfe32fa1Soh_ci        } else {
128dfe32fa1Soh_ci            log_throw_error!(ErrCode::InvalidArgument, "[FATAL]Get attribute of bytes type failed, key: {}", key)
129dfe32fa1Soh_ci        }
130dfe32fa1Soh_ci    }
131dfe32fa1Soh_ci}
132dfe32fa1Soh_ci
133dfe32fa1Soh_ciimpl Display for AssetError {
134dfe32fa1Soh_ci    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
135dfe32fa1Soh_ci        write!(f, "[{}]: {}", self.code, self.msg)
136dfe32fa1Soh_ci    }
137dfe32fa1Soh_ci}
138dfe32fa1Soh_ci
139dfe32fa1Soh_ciimpl AssetError {
140dfe32fa1Soh_ci    /// Create an AssetError instance.
141dfe32fa1Soh_ci    pub fn new(code: ErrCode, msg: String) -> AssetError {
142dfe32fa1Soh_ci        loge!("{}", msg);
143dfe32fa1Soh_ci        AssetError { code, msg }
144dfe32fa1Soh_ci    }
145dfe32fa1Soh_ci}
146dfe32fa1Soh_ci
147dfe32fa1Soh_ciimpl From<io::Error> for AssetError {
148dfe32fa1Soh_ci    fn from(error: io::Error) -> Self {
149dfe32fa1Soh_ci        AssetError {
150dfe32fa1Soh_ci            code: (ErrCode::FileOperationError),
151dfe32fa1Soh_ci            msg: (format!("[FATAL]Backup db failed! error is [{error}]")),
152dfe32fa1Soh_ci        }
153dfe32fa1Soh_ci    }
154dfe32fa1Soh_ci}
155dfe32fa1Soh_ci
156dfe32fa1Soh_ciimpl_from_for_u32!(AuthType);
157dfe32fa1Soh_ciimpl_from_for_u32!(Accessibility);
158