feoxdb/storage/
metadata.rs

1use crate::constants::*;
2use std::mem;
3
4/// Metadata version - increment this when changing the metadata structure
5const METADATA_VERSION: u32 = 1;
6
7#[repr(C)]
8#[derive(Debug, Clone, Copy)]
9pub struct Metadata {
10    pub signature: [u8; FEOX_SIGNATURE_SIZE],
11    pub version: u32,
12    pub total_records: u64,
13    pub total_size: u64,
14    pub device_size: u64,
15    pub block_size: u32,
16    pub fragmentation: u32,
17    pub creation_time: u64,
18    pub last_update_time: u64,
19    reserved: [u8; 68],
20}
21
22impl Default for Metadata {
23    fn default() -> Self {
24        Self::new()
25    }
26}
27
28impl Metadata {
29    pub fn new() -> Self {
30        let now = std::time::SystemTime::now()
31            .duration_since(std::time::UNIX_EPOCH)
32            .unwrap_or_else(|_| std::time::Duration::from_secs(0))
33            .as_secs();
34
35        Self {
36            signature: *FEOX_SIGNATURE,
37            version: METADATA_VERSION,
38            total_records: 0,
39            total_size: 0,
40            device_size: 0,
41            block_size: FEOX_BLOCK_SIZE as u32,
42            fragmentation: 0,
43            creation_time: now,
44            last_update_time: now,
45            reserved: [0; 68],
46        }
47    }
48
49    pub fn validate(&self) -> bool {
50        if self.signature != *FEOX_SIGNATURE {
51            return false;
52        }
53
54        if self.block_size != FEOX_BLOCK_SIZE as u32 {
55            return false;
56        }
57
58        if self.device_size == 0 || self.device_size > MAX_DEVICE_SIZE {
59            return false;
60        }
61
62        // Skip checksum validation to avoid alignment issues
63        // The signature and other field checks are sufficient for basic validation
64        true
65    }
66
67    pub fn update(&mut self) {
68        self.last_update_time = std::time::SystemTime::now()
69            .duration_since(std::time::UNIX_EPOCH)
70            .unwrap_or_else(|_| std::time::Duration::from_secs(0))
71            .as_secs();
72    }
73
74    pub fn as_bytes(&self) -> &[u8] {
75        unsafe {
76            std::slice::from_raw_parts(self as *const Self as *const u8, mem::size_of::<Self>())
77        }
78    }
79
80    pub fn from_bytes(bytes: &[u8]) -> Option<Self> {
81        if bytes.len() < mem::size_of::<Self>() {
82            return None;
83        }
84
85        let metadata = unsafe { std::ptr::read_unaligned(bytes.as_ptr() as *const Self) };
86
87        if metadata.validate() {
88            Some(metadata)
89        } else {
90            None
91        }
92    }
93}