Skip to main content

reddb_file/serverless/
pointer.rs

1use super::*;
2
3#[derive(Debug, Clone, PartialEq, Eq)]
4pub struct ServerlessGenerationPointer {
5    pub namespace: String,
6    pub generation: u64,
7    pub manifest_relative_path: PathBuf,
8    pub manifest_bytes: u64,
9    pub manifest_checksum: u32,
10    pub manifest_content_hash: ServerlessContentHash,
11}
12
13impl ServerlessGenerationPointer {
14    pub fn from_manifest(plan: &ServerlessFilePlan, manifest: &ServerlessManifest) -> Self {
15        let manifest_bytes = manifest.encode();
16        Self {
17            namespace: plan.namespace.clone(),
18            generation: manifest.generation,
19            manifest_relative_path: PathBuf::from(format!(
20                "g{:020}/manifest.redpack",
21                manifest.generation
22            )),
23            manifest_bytes: manifest_bytes.len() as u64,
24            manifest_checksum: crc32(&manifest_bytes),
25            manifest_content_hash: ServerlessContentHash::from_bytes(&manifest_bytes),
26        }
27    }
28
29    pub fn write_to_path(&self, path: impl AsRef<Path>) -> RdbFileResult<()> {
30        write_current_pointer_bytes(path, &self.encode())
31    }
32
33    pub fn read_from_path(path: impl AsRef<Path>) -> RdbFileResult<Self> {
34        Self::decode(&fs::read(path)?)
35    }
36
37    pub fn encode(&self) -> Vec<u8> {
38        let mut out = Vec::new();
39        out.extend_from_slice(SERVERLESS_GENERATION_POINTER_MAGIC);
40        put_u16(&mut out, SERVERLESS_ARTIFACT_VERSION);
41        put_string(&mut out, &self.namespace);
42        put_u64(&mut out, self.generation);
43        put_string(&mut out, &self.manifest_relative_path.to_string_lossy());
44        put_u64(&mut out, self.manifest_bytes);
45        put_u32(&mut out, self.manifest_checksum);
46        put_content_hash(&mut out, self.manifest_content_hash);
47        let checksum = crc32(&out);
48        put_u32(&mut out, checksum);
49        out
50    }
51
52    pub fn decode(bytes: &[u8]) -> RdbFileResult<Self> {
53        verify_checksum(bytes)?;
54        let mut cursor = 0usize;
55        expect_magic(bytes, &mut cursor, SERVERLESS_GENERATION_POINTER_MAGIC)?;
56        let version = take_u16(bytes, &mut cursor)?;
57        if version != SERVERLESS_ARTIFACT_VERSION {
58            return Err(RdbFileError::InvalidOperation(format!(
59                "unsupported serverless generation pointer version {version}"
60            )));
61        }
62        let namespace = take_string(bytes, &mut cursor)?;
63        let generation = take_u64(bytes, &mut cursor)?;
64        let manifest_relative_path = PathBuf::from(take_string(bytes, &mut cursor)?);
65        let manifest_bytes = take_u64(bytes, &mut cursor)?;
66        let manifest_checksum = take_u32(bytes, &mut cursor)?;
67        let manifest_content_hash = take_content_hash(bytes, &mut cursor)?;
68        reject_trailing_bytes(bytes, cursor)?;
69        Ok(Self {
70            namespace,
71            generation,
72            manifest_relative_path,
73            manifest_bytes,
74            manifest_checksum,
75            manifest_content_hash,
76        })
77    }
78}