1 /* 2 * Copyright (C) 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 //! flag info module defines the flag info file format and methods for serialization 18 //! and deserialization 19 20 use crate::{read_str_from_bytes, read_u32_from_bytes, read_u8_from_bytes}; 21 use crate::{AconfigStorageError, StorageFileType}; 22 use anyhow::anyhow; 23 use std::fmt; 24 25 /// Flag info header struct 26 #[derive(PartialEq)] 27 pub struct FlagInfoHeader { 28 pub version: u32, 29 pub container: String, 30 pub file_type: u8, 31 pub file_size: u32, 32 pub num_flags: u32, 33 pub boolean_flag_offset: u32, 34 } 35 36 /// Implement debug print trait for header 37 impl fmt::Debug for FlagInfoHeader { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result38 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 39 writeln!( 40 f, 41 "Version: {}, Container: {}, File Type: {:?}, File Size: {}", 42 self.version, 43 self.container, 44 StorageFileType::try_from(self.file_type), 45 self.file_size 46 )?; 47 writeln!( 48 f, 49 "Num of Flags: {}, Boolean Flag Offset:{}", 50 self.num_flags, self.boolean_flag_offset 51 )?; 52 Ok(()) 53 } 54 } 55 56 impl FlagInfoHeader { 57 /// Serialize to bytes into_bytes(&self) -> Vec<u8>58 pub fn into_bytes(&self) -> Vec<u8> { 59 let mut result = Vec::new(); 60 result.extend_from_slice(&self.version.to_le_bytes()); 61 let container_bytes = self.container.as_bytes(); 62 result.extend_from_slice(&(container_bytes.len() as u32).to_le_bytes()); 63 result.extend_from_slice(container_bytes); 64 result.extend_from_slice(&self.file_type.to_le_bytes()); 65 result.extend_from_slice(&self.file_size.to_le_bytes()); 66 result.extend_from_slice(&self.num_flags.to_le_bytes()); 67 result.extend_from_slice(&self.boolean_flag_offset.to_le_bytes()); 68 result 69 } 70 71 /// Deserialize from bytes from_bytes(bytes: &[u8]) -> Result<Self, AconfigStorageError>72 pub fn from_bytes(bytes: &[u8]) -> Result<Self, AconfigStorageError> { 73 let mut head = 0; 74 let list = Self { 75 version: read_u32_from_bytes(bytes, &mut head)?, 76 container: read_str_from_bytes(bytes, &mut head)?, 77 file_type: read_u8_from_bytes(bytes, &mut head)?, 78 file_size: read_u32_from_bytes(bytes, &mut head)?, 79 num_flags: read_u32_from_bytes(bytes, &mut head)?, 80 boolean_flag_offset: read_u32_from_bytes(bytes, &mut head)?, 81 }; 82 if list.file_type != StorageFileType::FlagInfo as u8 { 83 return Err(AconfigStorageError::BytesParseFail(anyhow!( 84 "binary file is not a flag info file" 85 ))); 86 } 87 Ok(list) 88 } 89 } 90 91 /// bit field for flag info 92 #[derive(Clone, Debug, PartialEq, Eq)] 93 pub enum FlagInfoBit { 94 HasServerOverride = 1 << 0, 95 IsReadWrite = 1 << 1, 96 HasLocalOverride = 1 << 2, 97 } 98 99 /// Flag info node struct 100 #[derive(PartialEq, Clone)] 101 pub struct FlagInfoNode { 102 pub attributes: u8, 103 } 104 105 /// Implement debug print trait for node 106 impl fmt::Debug for FlagInfoNode { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result107 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 108 writeln!( 109 f, 110 "readwrite: {}, server override: {}, local override: {}", 111 self.attributes & (FlagInfoBit::IsReadWrite as u8) != 0, 112 self.attributes & (FlagInfoBit::HasServerOverride as u8) != 0, 113 self.attributes & (FlagInfoBit::HasLocalOverride as u8) != 0, 114 )?; 115 Ok(()) 116 } 117 } 118 119 impl FlagInfoNode { 120 /// Serialize to bytes into_bytes(&self) -> Vec<u8>121 pub fn into_bytes(&self) -> Vec<u8> { 122 let mut result = Vec::new(); 123 result.extend_from_slice(&self.attributes.to_le_bytes()); 124 result 125 } 126 127 /// Deserialize from bytes from_bytes(bytes: &[u8]) -> Result<Self, AconfigStorageError>128 pub fn from_bytes(bytes: &[u8]) -> Result<Self, AconfigStorageError> { 129 let mut head = 0; 130 let node = Self { attributes: read_u8_from_bytes(bytes, &mut head)? }; 131 Ok(node) 132 } 133 134 /// Create flag info node create(is_flag_rw: bool) -> Self135 pub fn create(is_flag_rw: bool) -> Self { 136 Self { attributes: if is_flag_rw { FlagInfoBit::IsReadWrite as u8 } else { 0u8 } } 137 } 138 } 139 140 /// Flag info list struct 141 #[derive(PartialEq)] 142 pub struct FlagInfoList { 143 pub header: FlagInfoHeader, 144 pub nodes: Vec<FlagInfoNode>, 145 } 146 147 /// Implement debug print trait for flag info list 148 impl fmt::Debug for FlagInfoList { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result149 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 150 writeln!(f, "Header:")?; 151 write!(f, "{:?}", self.header)?; 152 writeln!(f, "Nodes:")?; 153 for node in self.nodes.iter() { 154 write!(f, "{:?}", node)?; 155 } 156 Ok(()) 157 } 158 } 159 160 impl FlagInfoList { 161 /// Serialize to bytes into_bytes(&self) -> Vec<u8>162 pub fn into_bytes(&self) -> Vec<u8> { 163 [ 164 self.header.into_bytes(), 165 self.nodes.iter().map(|v| v.into_bytes()).collect::<Vec<_>>().concat(), 166 ] 167 .concat() 168 } 169 170 /// Deserialize from bytes from_bytes(bytes: &[u8]) -> Result<Self, AconfigStorageError>171 pub fn from_bytes(bytes: &[u8]) -> Result<Self, AconfigStorageError> { 172 let header = FlagInfoHeader::from_bytes(bytes)?; 173 let num_flags = header.num_flags; 174 let mut head = header.into_bytes().len(); 175 let nodes = (0..num_flags) 176 .map(|_| { 177 let node = FlagInfoNode::from_bytes(&bytes[head..])?; 178 head += node.into_bytes().len(); 179 Ok(node) 180 }) 181 .collect::<Result<Vec<_>, AconfigStorageError>>() 182 .map_err(|errmsg| { 183 AconfigStorageError::BytesParseFail(anyhow!( 184 "fail to parse flag info list: {}", 185 errmsg 186 )) 187 })?; 188 let list = Self { header, nodes }; 189 Ok(list) 190 } 191 } 192 193 #[cfg(test)] 194 mod tests { 195 use super::*; 196 use crate::test_utils::create_test_flag_info_list; 197 198 #[test] 199 // this test point locks down the value list serialization test_serialization()200 fn test_serialization() { 201 let flag_info_list = create_test_flag_info_list(); 202 203 let header: &FlagInfoHeader = &flag_info_list.header; 204 let reinterpreted_header = FlagInfoHeader::from_bytes(&header.into_bytes()); 205 assert!(reinterpreted_header.is_ok()); 206 assert_eq!(header, &reinterpreted_header.unwrap()); 207 208 let nodes: &Vec<FlagInfoNode> = &flag_info_list.nodes; 209 for node in nodes.iter() { 210 let reinterpreted_node = FlagInfoNode::from_bytes(&node.into_bytes()).unwrap(); 211 assert_eq!(node, &reinterpreted_node); 212 } 213 214 let flag_info_bytes = flag_info_list.into_bytes(); 215 let reinterpreted_info_list = FlagInfoList::from_bytes(&flag_info_bytes); 216 assert!(reinterpreted_info_list.is_ok()); 217 assert_eq!(&flag_info_list, &reinterpreted_info_list.unwrap()); 218 assert_eq!(flag_info_bytes.len() as u32, header.file_size); 219 } 220 221 #[test] 222 // this test point locks down that version number should be at the top of serialized 223 // bytes test_version_number()224 fn test_version_number() { 225 let flag_info_list = create_test_flag_info_list(); 226 let bytes = &flag_info_list.into_bytes(); 227 let mut head = 0; 228 let version = read_u32_from_bytes(bytes, &mut head).unwrap(); 229 assert_eq!(version, 1); 230 } 231 232 #[test] 233 // this test point locks down file type check test_file_type_check()234 fn test_file_type_check() { 235 let mut flag_info_list = create_test_flag_info_list(); 236 flag_info_list.header.file_type = 123u8; 237 let error = FlagInfoList::from_bytes(&flag_info_list.into_bytes()).unwrap_err(); 238 assert_eq!( 239 format!("{:?}", error), 240 format!("BytesParseFail(binary file is not a flag info file)") 241 ); 242 } 243 } 244