Skip to main content

reddb_file/serverless/
boot.rs

1use super::*;
2
3#[derive(Debug, Clone, PartialEq, Eq)]
4pub struct ServerlessBootIndexEntry {
5    pub kind: ServerlessPackKind,
6    pub relative_path: PathBuf,
7    pub required_first: bool,
8}
9
10impl ServerlessBootIndexEntry {
11    pub fn new(
12        kind: ServerlessPackKind,
13        relative_path: impl Into<PathBuf>,
14        required_first: bool,
15    ) -> Self {
16        Self {
17            kind,
18            relative_path: relative_path.into(),
19            required_first,
20        }
21    }
22}
23
24#[derive(Debug, Clone, PartialEq, Eq)]
25pub struct ServerlessBootIndex {
26    pub generation: u64,
27    pub entries: Vec<ServerlessBootIndexEntry>,
28}
29
30impl ServerlessBootIndex {
31    pub fn from_plan(plan: &ServerlessFilePlan) -> Self {
32        let mut entries = Vec::new();
33        for path in plan.cold_start_order() {
34            entries.push(ServerlessBootIndexEntry::new(
35                kind_for_artifact_path(&path),
36                relative_to_generation_dir(&path),
37                true,
38            ));
39        }
40        for path in ServerlessBootPlan::cold(plan).lazy_after_open {
41            entries.push(ServerlessBootIndexEntry::new(
42                kind_for_artifact_path(&path),
43                relative_to_generation_dir(&path),
44                false,
45            ));
46        }
47        Self {
48            generation: plan.generation,
49            entries,
50        }
51    }
52
53    pub fn required_first(&self) -> Vec<PathBuf> {
54        self.entries
55            .iter()
56            .filter(|entry| entry.required_first)
57            .map(|entry| entry.relative_path.clone())
58            .collect()
59    }
60
61    pub fn lazy_after_open(&self) -> Vec<PathBuf> {
62        self.entries
63            .iter()
64            .filter(|entry| !entry.required_first)
65            .map(|entry| entry.relative_path.clone())
66            .collect()
67    }
68
69    pub fn write_to_path(&self, path: impl AsRef<Path>) -> RdbFileResult<()> {
70        write_bytes(path, &self.encode())
71    }
72
73    pub fn read_from_path(path: impl AsRef<Path>) -> RdbFileResult<Self> {
74        Self::decode(&fs::read(path)?)
75    }
76
77    pub fn encode(&self) -> Vec<u8> {
78        let mut out = Vec::new();
79        out.extend_from_slice(SERVERLESS_BOOT_INDEX_MAGIC);
80        put_u16(&mut out, SERVERLESS_ARTIFACT_VERSION);
81        put_u64(&mut out, self.generation);
82        put_u32(&mut out, self.entries.len() as u32);
83        for entry in &self.entries {
84            out.push(u8::from(entry.kind));
85            out.push(u8::from(entry.required_first));
86            put_string(&mut out, &entry.relative_path.to_string_lossy());
87        }
88        let checksum = crc32(&out);
89        put_u32(&mut out, checksum);
90        out
91    }
92
93    pub fn decode(bytes: &[u8]) -> RdbFileResult<Self> {
94        verify_checksum(bytes)?;
95        let mut cursor = 0usize;
96        expect_magic(bytes, &mut cursor, SERVERLESS_BOOT_INDEX_MAGIC)?;
97        let version = take_u16(bytes, &mut cursor)?;
98        if version != SERVERLESS_ARTIFACT_VERSION {
99            return Err(RdbFileError::InvalidOperation(format!(
100                "unsupported serverless boot-index version {version}"
101            )));
102        }
103        let generation = take_u64(bytes, &mut cursor)?;
104        let count = take_u32(bytes, &mut cursor)? as usize;
105        let mut entries = Vec::with_capacity(count);
106        for _ in 0..count {
107            let kind = ServerlessPackKind::try_from(take_u8(bytes, &mut cursor)?)?;
108            let required_first = take_u8(bytes, &mut cursor)? != 0;
109            let relative_path = PathBuf::from(take_string(bytes, &mut cursor)?);
110            entries.push(ServerlessBootIndexEntry {
111                kind,
112                relative_path,
113                required_first,
114            });
115        }
116        reject_trailing_bytes(bytes, cursor)?;
117        Ok(Self {
118            generation,
119            entries,
120        })
121    }
122}