use bytemuck::{Pod, Zeroable};
pub const MANIFEST_MAGIC: u32 = 0x47444D4D;
pub const MANIFEST_VERSION: u32 = 1;
#[repr(C)]
#[derive(Clone, Copy, Debug, Pod, Zeroable)]
pub struct Manifest {
pub magic: u32,
pub version: u32,
pub next_node_id: u64,
pub next_edge_id: u64,
pub checkpoint_lsn: u64,
pub last_committed_tx: u64,
}
impl Manifest {
pub fn new() -> Self {
Self {
magic: MANIFEST_MAGIC,
version: MANIFEST_VERSION,
next_node_id: 0,
next_edge_id: 0,
checkpoint_lsn: 0,
last_committed_tx: 0,
}
}
pub fn validate(&self) -> anyhow::Result<()> {
if self.magic != MANIFEST_MAGIC {
anyhow::bail!(
"Invalid manifest magic: expected 0x{:08X}, got 0x{:08X}",
MANIFEST_MAGIC,
self.magic
);
}
if self.version > MANIFEST_VERSION {
anyhow::bail!(
"Unsupported manifest version: {} (supported: {})",
self.version,
MANIFEST_VERSION
);
}
Ok(())
}
}
impl Default for Manifest {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_manifest_new() {
let manifest = Manifest::new();
assert_eq!(manifest.magic, MANIFEST_MAGIC);
assert_eq!(manifest.version, MANIFEST_VERSION);
assert_eq!(manifest.next_node_id, 0);
assert_eq!(manifest.next_edge_id, 0);
assert_eq!(manifest.checkpoint_lsn, 0);
assert_eq!(manifest.last_committed_tx, 0);
}
#[test]
fn test_manifest_validate_valid() {
let manifest = Manifest::new();
assert!(manifest.validate().is_ok());
}
#[test]
fn test_manifest_validate_invalid_magic() {
let mut manifest = Manifest::new();
manifest.magic = 0xDEADBEEF;
assert!(manifest.validate().is_err());
}
#[test]
fn test_manifest_validate_unsupported_version() {
let mut manifest = Manifest::new();
manifest.version = MANIFEST_VERSION + 1;
assert!(manifest.validate().is_err());
}
}