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