Coverage Report

Created: 2025-09-19 09:35

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