chrome_cache_parser/
cache_address.rs

1use std::fmt::{self, Debug, Formatter};
2use zerocopy::{FromBytes, FromZeroes};
3
4use crate::{CCPError, CCPResult};
5
6extern crate static_assertions as sa;
7
8const FILE_TYPE_MASK: u32 = 0x70000000;
9const FILE_TYPE_OFFSET: u32 = 28;
10const FILE_NAME_MASK: u32 = 0x0FFFFFFF;
11const FILE_SELECTOR_MASK: u32 = 0x00ff0000;
12const FILE_SELECTOR_OFFSET: u32 = 16;
13const START_BLOCK_MASK: u32 = 0x0000FFFF;
14const NUM_BLOCKS_MASK: u32 = 0x03000000;
15const NUM_BLOCKS_OFFSET: u32 = 24;
16
17#[derive(Debug, PartialEq)]
18pub enum FileType {
19    External = 0,
20    Rankings = 1,
21    Block256 = 2,
22    Block1k = 3,
23    Block4k = 4,
24    BlockFiles = 5,
25    BlockEntries = 6,
26    BlockEvicted = 7,
27}
28
29impl FileType {
30    pub fn block_size(&self) -> CCPResult<usize> {
31        match &self {
32            FileType::Block256 => Ok(256),
33            FileType::Block1k => Ok(1024),
34            FileType::Block4k => Ok(1024 * 4),
35            _ => Err(CCPError::InvalidState(
36                "Block size requested for non block file".to_string(),
37            )),
38        }
39    }
40}
41
42// See: https://chromium.googlesource.com/chromium/src/net/+/ddbc6c5954c4bee29902082eb9052405e83abc02/disk_cache/disk_format_base.h#28
43#[derive(Copy, Clone, FromZeroes, FromBytes)]
44#[repr(C)]
45pub struct CacheAddr {
46    pub value: u32,
47}
48
49pub const CACHE_ADDRESS_SIZE: usize = std::mem::size_of::<CacheAddr>();
50
51sa::const_assert_eq!(CACHE_ADDRESS_SIZE, 4);
52
53// See: https://chromium.googlesource.com/chromium/src/net/+/ddbc6c5954c4bee29902082eb9052405e83abc02/disk_cache/addr.h
54impl CacheAddr {
55    pub fn from(value: u32) -> CacheAddr {
56        CacheAddr { value }
57    }
58
59    pub fn is_initialized(&self) -> bool {
60        self.value != 0
61    }
62
63    pub fn file_type(&self) -> FileType {
64        match (self.value & FILE_TYPE_MASK) >> FILE_TYPE_OFFSET {
65            0 => FileType::External,
66            1 => FileType::Rankings,
67            2 => FileType::Block256,
68            3 => FileType::Block1k,
69            4 => FileType::Block4k,
70            5 => FileType::BlockFiles,
71            6 => FileType::BlockEntries,
72            7 => FileType::BlockEvicted,
73            _ => panic!("u32 shifted 28 bits isn't in (0..8)?"),
74        }
75    }
76
77    pub fn file_number(&self) -> u32 {
78        match self.file_type() {
79            FileType::External => self.value & FILE_NAME_MASK,
80            _ => (self.value & FILE_SELECTOR_MASK) >> FILE_SELECTOR_OFFSET,
81        }
82    }
83
84    pub fn start_block(&self) -> u32 {
85        self.value & START_BLOCK_MASK
86    }
87
88    pub fn num_blocks(&self) -> u32 {
89        ((self.value & NUM_BLOCKS_MASK) >> NUM_BLOCKS_OFFSET) + 1
90    }
91}
92
93impl Debug for CacheAddr {
94    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
95        write!(f, "0x{:X?} (initialized: {:?}, file_type: {:?} file_number: {:?}, start_block: {:?}, num_blocks: {:?})",
96               self.value, self.is_initialized(), self.file_type(), self.file_number(), self.start_block(), self.num_blocks())
97    }
98}