Skip to main content

faf_fafb/
flags.rs

1//! FAFB Feature Flags
2//!
3//! Bit flags for optional features in .fafb files.
4//! Readers MUST ignore unknown flags and continue processing.
5
6/// Content is zstd compressed
7pub const FLAG_COMPRESSED: u16 = 0b0000_0000_0000_0001;
8
9/// Contains pre-computed embeddings
10pub const FLAG_EMBEDDINGS: u16 = 0b0000_0000_0000_0010;
11
12/// Contains token boundaries
13pub const FLAG_TOKENIZED: u16 = 0b0000_0000_0000_0100;
14
15/// Contains attention weights
16pub const FLAG_WEIGHTED: u16 = 0b0000_0000_0000_1000;
17
18/// Contains model-specific hints
19pub const FLAG_MODEL_HINTS: u16 = 0b0000_0000_0001_0000;
20
21/// Contains cryptographic signature
22pub const FLAG_SIGNED: u16 = 0b0000_0000_0010_0000;
23
24/// Contains a string table (always set in unified format)
25pub const FLAG_STRING_TABLE: u16 = 0b0000_0000_0100_0000;
26
27/// File is output of chain resolution (enterprise)
28pub const FLAG_RESOLVED: u16 = 0b0000_0000_1000_0000;
29
30/// Carries `__provenance__` (spec 2.0 structural; this crate does not write it)
31pub const FLAG_PROVENANCE: u16 = 0b0000_0001_0000_0000;
32
33/// Carries `__members__` (spec 2.0 structural; this crate does not write it)
34pub const FLAG_MEMBERS: u16 = 0b0000_0010_0000_0000;
35
36// Unassigned: bits 10-15
37
38/// Helper struct for working with flags
39#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
40pub struct Flags(pub u16);
41
42impl Flags {
43    /// Create new empty flags
44    pub const fn new() -> Self {
45        Self(0)
46    }
47
48    /// Create flags from raw u16
49    pub const fn from_raw(raw: u16) -> Self {
50        Self(raw)
51    }
52
53    /// Get raw u16 value
54    pub const fn raw(&self) -> u16 {
55        self.0
56    }
57
58    /// Check if compressed flag is set
59    pub const fn is_compressed(&self) -> bool {
60        self.0 & FLAG_COMPRESSED != 0
61    }
62
63    /// Check if embeddings flag is set
64    pub const fn has_embeddings(&self) -> bool {
65        self.0 & FLAG_EMBEDDINGS != 0
66    }
67
68    /// Check if tokenized flag is set
69    pub const fn is_tokenized(&self) -> bool {
70        self.0 & FLAG_TOKENIZED != 0
71    }
72
73    /// Check if weighted flag is set
74    pub const fn has_weights(&self) -> bool {
75        self.0 & FLAG_WEIGHTED != 0
76    }
77
78    /// Check if model hints flag is set
79    pub const fn has_model_hints(&self) -> bool {
80        self.0 & FLAG_MODEL_HINTS != 0
81    }
82
83    /// Check if signed flag is set
84    pub const fn is_signed(&self) -> bool {
85        self.0 & FLAG_SIGNED != 0
86    }
87
88    /// Set compressed flag
89    pub fn set_compressed(&mut self, value: bool) {
90        if value {
91            self.0 |= FLAG_COMPRESSED;
92        } else {
93            self.0 &= !FLAG_COMPRESSED;
94        }
95    }
96
97    /// Set embeddings flag
98    pub fn set_embeddings(&mut self, value: bool) {
99        if value {
100            self.0 |= FLAG_EMBEDDINGS;
101        } else {
102            self.0 &= !FLAG_EMBEDDINGS;
103        }
104    }
105
106    /// Set tokenized flag
107    pub fn set_tokenized(&mut self, value: bool) {
108        if value {
109            self.0 |= FLAG_TOKENIZED;
110        } else {
111            self.0 &= !FLAG_TOKENIZED;
112        }
113    }
114
115    /// Set weighted flag
116    pub fn set_weighted(&mut self, value: bool) {
117        if value {
118            self.0 |= FLAG_WEIGHTED;
119        } else {
120            self.0 &= !FLAG_WEIGHTED;
121        }
122    }
123
124    /// Set model hints flag
125    pub fn set_model_hints(&mut self, value: bool) {
126        if value {
127            self.0 |= FLAG_MODEL_HINTS;
128        } else {
129            self.0 &= !FLAG_MODEL_HINTS;
130        }
131    }
132
133    /// Set signed flag
134    pub fn set_signed(&mut self, value: bool) {
135        if value {
136            self.0 |= FLAG_SIGNED;
137        } else {
138            self.0 &= !FLAG_SIGNED;
139        }
140    }
141
142    /// Check if string table flag is set
143    pub const fn has_string_table(&self) -> bool {
144        self.0 & FLAG_STRING_TABLE != 0
145    }
146
147    /// Set string table flag
148    pub fn set_string_table(&mut self, value: bool) {
149        if value {
150            self.0 |= FLAG_STRING_TABLE;
151        } else {
152            self.0 &= !FLAG_STRING_TABLE;
153        }
154    }
155
156    /// Check if resolved flag is set (enterprise chain resolution)
157    pub const fn is_resolved(&self) -> bool {
158        self.0 & FLAG_RESOLVED != 0
159    }
160
161    /// Set resolved flag (enterprise chain resolution)
162    pub fn set_resolved(&mut self, value: bool) {
163        if value {
164            self.0 |= FLAG_RESOLVED;
165        } else {
166            self.0 &= !FLAG_RESOLVED;
167        }
168    }
169}
170
171impl From<u16> for Flags {
172    fn from(raw: u16) -> Self {
173        Self(raw)
174    }
175}
176
177impl From<Flags> for u16 {
178    fn from(flags: Flags) -> Self {
179        flags.0
180    }
181}
182
183#[cfg(test)]
184mod tests {
185    use super::*;
186
187    #[test]
188    fn test_flag_bits() {
189        assert_eq!(FLAG_COMPRESSED, 1);
190        assert_eq!(FLAG_EMBEDDINGS, 2);
191        assert_eq!(FLAG_TOKENIZED, 4);
192        assert_eq!(FLAG_WEIGHTED, 8);
193        assert_eq!(FLAG_MODEL_HINTS, 16);
194        assert_eq!(FLAG_SIGNED, 32);
195        assert_eq!(FLAG_STRING_TABLE, 64);
196        assert_eq!(FLAG_RESOLVED, 128);
197        assert_eq!(FLAG_PROVENANCE, 256);
198        assert_eq!(FLAG_MEMBERS, 512);
199    }
200
201    #[test]
202    fn test_flags_default() {
203        let flags = Flags::new();
204        assert_eq!(flags.raw(), 0);
205        assert!(!flags.is_compressed());
206        assert!(!flags.has_embeddings());
207    }
208
209    #[test]
210    fn test_flags_set_get() {
211        let mut flags = Flags::new();
212        flags.set_compressed(true);
213        flags.set_embeddings(true);
214
215        assert!(flags.is_compressed());
216        assert!(flags.has_embeddings());
217        assert!(!flags.is_tokenized());
218
219        assert_eq!(flags.raw(), FLAG_COMPRESSED | FLAG_EMBEDDINGS);
220    }
221
222    #[test]
223    fn test_flags_unset() {
224        let mut flags = Flags::from_raw(FLAG_COMPRESSED | FLAG_EMBEDDINGS);
225        flags.set_compressed(false);
226
227        assert!(!flags.is_compressed());
228        assert!(flags.has_embeddings());
229    }
230
231    #[test]
232    fn test_resolved_flag() {
233        let mut flags = Flags::new();
234        assert!(!flags.is_resolved());
235        flags.set_resolved(true);
236        assert!(flags.is_resolved());
237        assert_eq!(flags.raw() & FLAG_RESOLVED, FLAG_RESOLVED);
238    }
239}