diff --git a/tools/aconfig/src/storage/package_table.rs b/tools/aconfig/src/storage/package_table.rs index a6ce013309..940c5b2f64 100644 --- a/tools/aconfig/src/storage/package_table.rs +++ b/tools/aconfig/src/storage/package_table.rs @@ -87,6 +87,7 @@ impl PackageTableNode { } } +#[derive(PartialEq, Debug)] pub struct PackageTable { pub header: PackageTableHeader, pub buckets: Vec>, @@ -104,11 +105,17 @@ impl PackageTable { nodes: packages.iter().map(|pkg| PackageTableNode::new(pkg, num_buckets)).collect(), }; + // initialize all header fields + table.header.bucket_offset = table.header.as_bytes().len() as u32; + table.header.node_offset = table.header.bucket_offset + num_buckets * 4; + table.header.file_size = table.header.node_offset + + table.nodes.iter().map(|x| x.as_bytes().len()).sum::() as u32; + // sort nodes by bucket index for efficiency table.nodes.sort_by(|a, b| a.bucket_index.cmp(&b.bucket_index)); // fill all node offset - let mut offset = 0; + let mut offset = table.header.node_offset; for i in 0..table.nodes.len() { let node_bucket_idx = table.nodes[i].bucket_index; let next_node_bucket_idx = if i + 1 < table.nodes.len() { @@ -129,12 +136,6 @@ impl PackageTable { } } - // fill table region offset - table.header.bucket_offset = table.header.as_bytes().len() as u32; - table.header.node_offset = table.header.bucket_offset + num_buckets * 4; - table.header.file_size = table.header.node_offset - + table.nodes.iter().map(|x| x.as_bytes().len()).sum::() as u32; - Ok(table) } @@ -190,6 +191,32 @@ mod tests { } } + impl PackageTable { + // test only method to deserialize back into the table struct + fn from_bytes(bytes: &[u8]) -> Result { + let header = PackageTableHeader::from_bytes(bytes)?; + let num_packages = header.num_packages; + let num_buckets = storage::get_table_size(num_packages)?; + let mut head = header.as_bytes().len(); + let buckets = (0..num_buckets) + .map(|_| match read_u32_from_bytes(bytes, &mut head).unwrap() { + 0 => None, + val => Some(val), + }) + .collect(); + let nodes = (0..num_packages) + .map(|_| { + let node = PackageTableNode::from_bytes(&bytes[head..], num_buckets).unwrap(); + head += node.as_bytes().len(); + node + }) + .collect(); + + let table = Self { header, buckets, nodes }; + Ok(table) + } + } + pub fn create_test_package_table() -> Result { let caches = parse_all_test_flags(); let packages = group_flags_by_package(caches.iter()); @@ -214,7 +241,7 @@ mod tests { assert_eq!(header, &expected_header); let buckets: &Vec> = &package_table.as_ref().unwrap().buckets; - let expected: Vec> = vec![Some(0), None, None, Some(50), None, None, None]; + let expected: Vec> = vec![Some(58), None, None, Some(108), None, None, None]; assert_eq!(buckets, &expected); let nodes: &Vec = &package_table.as_ref().unwrap().nodes; @@ -231,7 +258,7 @@ mod tests { package_name: String::from("com.android.aconfig.storage.test_1"), package_id: 0, boolean_offset: 0, - next_offset: Some(100), + next_offset: Some(158), bucket_index: 3, }; assert_eq!(nodes[1], second_node_expected); @@ -250,18 +277,23 @@ mod tests { fn test_serialization() { let package_table = create_test_package_table(); assert!(package_table.is_ok()); + let package_table = package_table.unwrap(); - let header: &PackageTableHeader = &package_table.as_ref().unwrap().header; + let header: &PackageTableHeader = &package_table.header; let reinterpreted_header = PackageTableHeader::from_bytes(&header.as_bytes()); assert!(reinterpreted_header.is_ok()); assert_eq!(header, &reinterpreted_header.unwrap()); - let nodes: &Vec = &package_table.as_ref().unwrap().nodes; + let nodes: &Vec = &package_table.nodes; let num_buckets = storage::get_table_size(header.num_packages).unwrap(); for node in nodes.iter() { let reinterpreted_node = PackageTableNode::from_bytes(&node.as_bytes(), num_buckets); assert!(reinterpreted_node.is_ok()); assert_eq!(node, &reinterpreted_node.unwrap()); } + + let reinterpreted_table = PackageTable::from_bytes(&package_table.as_bytes()); + assert!(reinterpreted_table.is_ok()); + assert_eq!(&package_table, &reinterpreted_table.unwrap()); } }