Skip to main content

rvf_types/
flags.rs

1//! Segment flags bitfield for the RVF format.
2
3/// Bitfield wrapper around the 16-bit segment flags.
4///
5/// Bits 12-15 are reserved and must be zero.
6#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
7#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
8#[repr(transparent)]
9pub struct SegmentFlags(u16);
10
11impl SegmentFlags {
12    /// Payload is compressed per the `compression` header field.
13    pub const COMPRESSED: u16 = 0x0001;
14    /// Payload is encrypted (key info in CRYPTO_SEG / manifest).
15    pub const ENCRYPTED: u16 = 0x0002;
16    /// A signature footer follows the payload.
17    pub const SIGNED: u16 = 0x0004;
18    /// Segment is immutable (compaction output).
19    pub const SEALED: u16 = 0x0008;
20    /// Segment is a partial / streaming write.
21    pub const PARTIAL: u16 = 0x0010;
22    /// Segment logically deletes a prior segment.
23    pub const TOMBSTONE: u16 = 0x0020;
24    /// Segment contains temperature-promoted (hot) data.
25    pub const HOT: u16 = 0x0040;
26    /// Segment contains overlay / delta data.
27    pub const OVERLAY: u16 = 0x0080;
28    /// Segment contains a full snapshot (not delta).
29    pub const SNAPSHOT: u16 = 0x0100;
30    /// Segment is a safe rollback point.
31    pub const CHECKPOINT: u16 = 0x0200;
32    /// Segment was produced inside an attested TEE environment.
33    pub const ATTESTED: u16 = 0x0400;
34    /// File carries DNA-style lineage provenance metadata.
35    pub const HAS_LINEAGE: u16 = 0x0800;
36
37    /// Mask for all defined flag bits.
38    const KNOWN_MASK: u16 = 0x0FFF;
39
40    /// Create an empty flags value (no flags set).
41    #[inline]
42    pub const fn empty() -> Self {
43        Self(0)
44    }
45
46    /// Create flags from a raw `u16`. Reserved bits are masked off.
47    #[inline]
48    pub const fn from_raw(raw: u16) -> Self {
49        Self(raw & Self::KNOWN_MASK)
50    }
51
52    /// Return the raw `u16` representation.
53    #[inline]
54    pub const fn bits(self) -> u16 {
55        self.0
56    }
57
58    /// Check whether a specific flag bit is set.
59    #[inline]
60    pub const fn contains(self, flag: u16) -> bool {
61        self.0 & flag == flag
62    }
63
64    /// Set a flag bit.
65    #[inline]
66    pub const fn with(self, flag: u16) -> Self {
67        Self(self.0 | (flag & Self::KNOWN_MASK))
68    }
69
70    /// Clear a flag bit.
71    #[inline]
72    pub const fn without(self, flag: u16) -> Self {
73        Self(self.0 & !flag)
74    }
75
76    /// Returns true if no flags are set.
77    #[inline]
78    pub const fn is_empty(self) -> bool {
79        self.0 == 0
80    }
81}
82
83#[cfg(test)]
84mod tests {
85    use super::*;
86
87    #[test]
88    fn empty_flags() {
89        let f = SegmentFlags::empty();
90        assert!(f.is_empty());
91        assert_eq!(f.bits(), 0);
92    }
93
94    #[test]
95    fn set_and_check_flags() {
96        let f = SegmentFlags::empty()
97            .with(SegmentFlags::COMPRESSED)
98            .with(SegmentFlags::SEALED);
99        assert!(f.contains(SegmentFlags::COMPRESSED));
100        assert!(f.contains(SegmentFlags::SEALED));
101        assert!(!f.contains(SegmentFlags::ENCRYPTED));
102    }
103
104    #[test]
105    fn clear_flag() {
106        let f = SegmentFlags::empty()
107            .with(SegmentFlags::COMPRESSED)
108            .with(SegmentFlags::SIGNED)
109            .without(SegmentFlags::COMPRESSED);
110        assert!(!f.contains(SegmentFlags::COMPRESSED));
111        assert!(f.contains(SegmentFlags::SIGNED));
112    }
113
114    #[test]
115    fn reserved_bits_masked() {
116        let f = SegmentFlags::from_raw(0xFFFF);
117        assert_eq!(f.bits(), 0x0FFF);
118    }
119
120    #[test]
121    fn all_known_flags() {
122        let all = SegmentFlags::empty()
123            .with(SegmentFlags::COMPRESSED)
124            .with(SegmentFlags::ENCRYPTED)
125            .with(SegmentFlags::SIGNED)
126            .with(SegmentFlags::SEALED)
127            .with(SegmentFlags::PARTIAL)
128            .with(SegmentFlags::TOMBSTONE)
129            .with(SegmentFlags::HOT)
130            .with(SegmentFlags::OVERLAY)
131            .with(SegmentFlags::SNAPSHOT)
132            .with(SegmentFlags::CHECKPOINT)
133            .with(SegmentFlags::ATTESTED)
134            .with(SegmentFlags::HAS_LINEAGE);
135        assert_eq!(all.bits(), 0x0FFF);
136    }
137}