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