reddb_file/serverless/
pointer.rs1use 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}