reddb-io-file 1.11.0

RedDB file artifact layer: single-file .rdb layout, WAL, snapshots, checkpoints, locks, and recovery.
Documentation
use super::*;

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ServerlessGenerationPointer {
    pub namespace: String,
    pub generation: u64,
    pub manifest_relative_path: PathBuf,
    pub manifest_bytes: u64,
    pub manifest_checksum: u32,
    pub manifest_content_hash: ServerlessContentHash,
}

impl ServerlessGenerationPointer {
    pub fn from_manifest(plan: &ServerlessFilePlan, manifest: &ServerlessManifest) -> Self {
        let manifest_bytes = manifest.encode();
        Self {
            namespace: plan.namespace.clone(),
            generation: manifest.generation,
            manifest_relative_path: PathBuf::from(format!(
                "g{:020}/manifest.redpack",
                manifest.generation
            )),
            manifest_bytes: manifest_bytes.len() as u64,
            manifest_checksum: crc32(&manifest_bytes),
            manifest_content_hash: ServerlessContentHash::from_bytes(&manifest_bytes),
        }
    }

    pub fn write_to_path(&self, path: impl AsRef<Path>) -> RdbFileResult<()> {
        write_current_pointer_bytes(path, &self.encode())
    }

    pub fn read_from_path(path: impl AsRef<Path>) -> RdbFileResult<Self> {
        Self::decode(&fs::read(path)?)
    }

    pub fn encode(&self) -> Vec<u8> {
        let mut out = Vec::new();
        out.extend_from_slice(SERVERLESS_GENERATION_POINTER_MAGIC);
        put_u16(&mut out, SERVERLESS_ARTIFACT_VERSION);
        put_string(&mut out, &self.namespace);
        put_u64(&mut out, self.generation);
        put_string(&mut out, &self.manifest_relative_path.to_string_lossy());
        put_u64(&mut out, self.manifest_bytes);
        put_u32(&mut out, self.manifest_checksum);
        put_content_hash(&mut out, self.manifest_content_hash);
        let checksum = crc32(&out);
        put_u32(&mut out, checksum);
        out
    }

    pub fn decode(bytes: &[u8]) -> RdbFileResult<Self> {
        verify_checksum(bytes)?;
        let mut cursor = 0usize;
        expect_magic(bytes, &mut cursor, SERVERLESS_GENERATION_POINTER_MAGIC)?;
        let version = take_u16(bytes, &mut cursor)?;
        if version != SERVERLESS_ARTIFACT_VERSION {
            return Err(RdbFileError::InvalidOperation(format!(
                "unsupported serverless generation pointer version {version}"
            )));
        }
        let namespace = take_string(bytes, &mut cursor)?;
        let generation = take_u64(bytes, &mut cursor)?;
        let manifest_relative_path = PathBuf::from(take_string(bytes, &mut cursor)?);
        let manifest_bytes = take_u64(bytes, &mut cursor)?;
        let manifest_checksum = take_u32(bytes, &mut cursor)?;
        let manifest_content_hash = take_content_hash(bytes, &mut cursor)?;
        reject_trailing_bytes(bytes, cursor)?;
        Ok(Self {
            namespace,
            generation,
            manifest_relative_path,
            manifest_bytes,
            manifest_checksum,
            manifest_content_hash,
        })
    }
}