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 serde::{Deserialize, Serialize}; 24 use std::fmt; 25 26 /// Flag info header struct 27 #[derive(PartialEq, Serialize, Deserialize)] 28 pub struct FlagInfoHeader { 29 pub version: u32, 30 pub container: String, 31 pub file_type: u8, 32 pub file_size: u32, 33 pub num_flags: u32, 34 pub boolean_flag_offset: u32, 35 } 36 37 /// Implement debug print trait for header 38 impl fmt::Debug for FlagInfoHeader { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result39 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 40 writeln!( 41 f, 42 "Version: {}, Container: {}, File Type: {:?}, File Size: {}", 43 self.version, 44 self.container, 45 StorageFileType::try_from(self.file_type), 46 self.file_size 47 )?; 48 writeln!( 49 f, 50 "Num of Flags: {}, Boolean Flag Offset:{}", 51 self.num_flags, self.boolean_flag_offset 52 )?; 53 Ok(()) 54 } 55 } 56 57 impl FlagInfoHeader { 58 /// Serialize to bytes into_bytes(&self) -> Vec<u8>59 pub fn into_bytes(&self) -> Vec<u8> { 60 let mut result = Vec::new(); 61 result.extend_from_slice(&self.version.to_le_bytes()); 62 let container_bytes = self.container.as_bytes(); 63 result.extend_from_slice(&(container_bytes.len() as u32).to_le_bytes()); 64 result.extend_from_slice(container_bytes); 65 result.extend_from_slice(&self.file_type.to_le_bytes()); 66 result.extend_from_slice(&self.file_size.to_le_bytes()); 67 result.extend_from_slice(&self.num_flags.to_le_bytes()); 68 result.extend_from_slice(&self.boolean_flag_offset.to_le_bytes()); 69 result 70 } 71 72 /// Deserialize from bytes from_bytes(bytes: &[u8]) -> Result<Self, AconfigStorageError>73 pub fn from_bytes(bytes: &[u8]) -> Result<Self, AconfigStorageError> { 74 let mut head = 0; 75 let list = Self { 76 version: read_u32_from_bytes(bytes, &mut head)?, 77 container: read_str_from_bytes(bytes, &mut head)?, 78 file_type: read_u8_from_bytes(bytes, &mut head)?, 79 file_size: read_u32_from_bytes(bytes, &mut head)?, 80 num_flags: read_u32_from_bytes(bytes, &mut head)?, 81 boolean_flag_offset: read_u32_from_bytes(bytes, &mut head)?, 82 }; 83 if list.file_type != StorageFileType::FlagInfo as u8 { 84 return Err(AconfigStorageError::BytesParseFail(anyhow!( 85 "binary file is not a flag info file" 86 ))); 87 } 88 Ok(list) 89 } 90 } 91 92 /// bit field for flag info 93 #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] 94 pub enum FlagInfoBit { 95 HasServerOverride = 1 << 0, 96 IsReadWrite = 1 << 1, 97 HasLocalOverride = 1 << 2, 98 } 99 100 /// Flag info node struct 101 #[derive(PartialEq, Clone, Serialize, Deserialize)] 102 pub struct FlagInfoNode { 103 pub attributes: u8, 104 } 105 106 /// Implement debug print trait for node 107 impl fmt::Debug for FlagInfoNode { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result108 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 109 writeln!( 110 f, 111 "readwrite: {}, server override: {}, local override: {}", 112 self.attributes & (FlagInfoBit::IsReadWrite as u8) != 0, 113 self.attributes & (FlagInfoBit::HasServerOverride as u8) != 0, 114 self.attributes & (FlagInfoBit::HasLocalOverride as u8) != 0, 115 )?; 116 Ok(()) 117 } 118 } 119 120 impl FlagInfoNode { 121 /// Serialize to bytes into_bytes(&self) -> Vec<u8>122 pub fn into_bytes(&self) -> Vec<u8> { 123 let mut result = Vec::new(); 124 result.extend_from_slice(&self.attributes.to_le_bytes()); 125 result 126 } 127 128 /// Deserialize from bytes from_bytes(bytes: &[u8]) -> Result<Self, AconfigStorageError>129 pub fn from_bytes(bytes: &[u8]) -> Result<Self, AconfigStorageError> { 130 let mut head = 0; 131 let node = Self { attributes: read_u8_from_bytes(bytes, &mut head)? }; 132 Ok(node) 133 } 134 135 /// Create flag info node create(is_flag_rw: bool) -> Self136 pub fn create(is_flag_rw: bool) -> Self { 137 Self { attributes: if is_flag_rw { FlagInfoBit::IsReadWrite as u8 } else { 0u8 } } 138 } 139 } 140 141 /// Flag info list struct 142 #[derive(PartialEq, Serialize, Deserialize)] 143 pub struct FlagInfoList { 144 pub header: FlagInfoHeader, 145 pub nodes: Vec<FlagInfoNode>, 146 } 147 148 /// Implement debug print trait for flag info list 149 impl fmt::Debug for FlagInfoList { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result150 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 151 writeln!(f, "Header:")?; 152 write!(f, "{:?}", self.header)?; 153 writeln!(f, "Nodes:")?; 154 for node in self.nodes.iter() { 155 write!(f, "{:?}", node)?; 156 } 157 Ok(()) 158 } 159 } 160 161 impl FlagInfoList { 162 /// Serialize to bytes into_bytes(&self) -> Vec<u8>163 pub fn into_bytes(&self) -> Vec<u8> { 164 [ 165 self.header.into_bytes(), 166 self.nodes.iter().map(|v| v.into_bytes()).collect::<Vec<_>>().concat(), 167 ] 168 .concat() 169 } 170 171 /// Deserialize from bytes from_bytes(bytes: &[u8]) -> Result<Self, AconfigStorageError>172 pub fn from_bytes(bytes: &[u8]) -> Result<Self, AconfigStorageError> { 173 let header = FlagInfoHeader::from_bytes(bytes)?; 174 let num_flags = header.num_flags; 175 let mut head = header.into_bytes().len(); 176 let nodes = (0..num_flags) 177 .map(|_| { 178 let node = FlagInfoNode::from_bytes(&bytes[head..])?; 179 head += node.into_bytes().len(); 180 Ok(node) 181 }) 182 .collect::<Result<Vec<_>, AconfigStorageError>>() 183 .map_err(|errmsg| { 184 AconfigStorageError::BytesParseFail(anyhow!( 185 "fail to parse flag info list: {}", 186 errmsg 187 )) 188 })?; 189 let list = Self { header, nodes }; 190 Ok(list) 191 } 192 } 193 194 #[cfg(test)] 195 mod tests { 196 use super::*; 197 use crate::{ 198 test_utils::create_test_flag_info_list, DEFAULT_FILE_VERSION, MAX_SUPPORTED_FILE_VERSION, 199 }; 200 201 // this test point locks down the value list serialization 202 // TODO: b/376108268 - Use parameterized tests. 203 #[test] test_serialization_default()204 fn test_serialization_default() { 205 let flag_info_list = create_test_flag_info_list(DEFAULT_FILE_VERSION); 206 207 let header: &FlagInfoHeader = &flag_info_list.header; 208 let reinterpreted_header = FlagInfoHeader::from_bytes(&header.into_bytes()); 209 assert!(reinterpreted_header.is_ok()); 210 assert_eq!(header, &reinterpreted_header.unwrap()); 211 212 let nodes: &Vec<FlagInfoNode> = &flag_info_list.nodes; 213 for node in nodes.iter() { 214 let reinterpreted_node = FlagInfoNode::from_bytes(&node.into_bytes()).unwrap(); 215 assert_eq!(node, &reinterpreted_node); 216 } 217 218 let flag_info_bytes = flag_info_list.into_bytes(); 219 let reinterpreted_info_list = FlagInfoList::from_bytes(&flag_info_bytes); 220 assert!(reinterpreted_info_list.is_ok()); 221 assert_eq!(&flag_info_list, &reinterpreted_info_list.unwrap()); 222 assert_eq!(flag_info_bytes.len() as u32, header.file_size); 223 } 224 225 #[test] test_serialization_max()226 fn test_serialization_max() { 227 let flag_info_list = create_test_flag_info_list(MAX_SUPPORTED_FILE_VERSION); 228 229 let header: &FlagInfoHeader = &flag_info_list.header; 230 let reinterpreted_header = FlagInfoHeader::from_bytes(&header.into_bytes()); 231 assert!(reinterpreted_header.is_ok()); 232 assert_eq!(header, &reinterpreted_header.unwrap()); 233 234 let nodes: &Vec<FlagInfoNode> = &flag_info_list.nodes; 235 for node in nodes.iter() { 236 let reinterpreted_node = FlagInfoNode::from_bytes(&node.into_bytes()).unwrap(); 237 assert_eq!(node, &reinterpreted_node); 238 } 239 240 let flag_info_bytes = flag_info_list.into_bytes(); 241 let reinterpreted_info_list = FlagInfoList::from_bytes(&flag_info_bytes); 242 assert!(reinterpreted_info_list.is_ok()); 243 assert_eq!(&flag_info_list, &reinterpreted_info_list.unwrap()); 244 assert_eq!(flag_info_bytes.len() as u32, header.file_size); 245 } 246 247 // this test point locks down that version number should be at the top of serialized 248 // bytes 249 #[test] test_version_number()250 fn test_version_number() { 251 let flag_info_list = create_test_flag_info_list(DEFAULT_FILE_VERSION); 252 let bytes = &flag_info_list.into_bytes(); 253 let mut head = 0; 254 let version_from_file = read_u32_from_bytes(bytes, &mut head).unwrap(); 255 assert_eq!(version_from_file, DEFAULT_FILE_VERSION); 256 } 257 258 // this test point locks down file type check 259 #[test] test_file_type_check()260 fn test_file_type_check() { 261 let mut flag_info_list = create_test_flag_info_list(DEFAULT_FILE_VERSION); 262 flag_info_list.header.file_type = 123u8; 263 let error = FlagInfoList::from_bytes(&flag_info_list.into_bytes()).unwrap_err(); 264 assert_eq!( 265 format!("{:?}", error), 266 format!("BytesParseFail(binary file is not a flag info file)") 267 ); 268 } 269 } 270