1pub mod frame;
4pub mod golden;
5
6#[derive(Clone, Copy, Debug, Eq, PartialEq)]
8#[repr(u16)]
9pub enum FormatFamily {
10 Frame = 1,
12 Segment = 2,
14 VectorCodes = 3,
16 VectorFactors = 4,
18 VectorRescore = 5,
20 Columns = 6,
22 Alive = 7,
24 Postings = 8,
26 ChecksumTable = 9,
28 Manifest = 10,
30 Wal = 11,
32 GraphNodeBlocks = 12,
34 DocumentVersions = 13,
36 StoredMetadata = 14,
38 PurgeIntent = 15,
40 StoredText = 16,
42}
43
44impl FormatFamily {
45 #[must_use]
47 pub const fn id(self) -> u16 {
48 self as u16
49 }
50
51 pub(crate) const fn current_version(self) -> u16 {
52 match self {
53 Self::Manifest => 2,
54 Self::Frame
55 | Self::Segment
56 | Self::VectorCodes
57 | Self::VectorFactors
58 | Self::VectorRescore
59 | Self::Columns
60 | Self::Alive
61 | Self::Postings
62 | Self::ChecksumTable
63 | Self::Wal
64 | Self::GraphNodeBlocks
65 | Self::DocumentVersions
66 | Self::StoredMetadata
67 | Self::PurgeIntent
68 | Self::StoredText => 1,
69 }
70 }
71}
72
73#[derive(Clone, Copy, Debug, Eq, PartialEq)]
75pub struct FamilySpec {
76 pub family: FormatFamily,
78 pub current_version: u16,
80 pub minimum_accepted_version: u16,
82 pub maximum_accepted_version: u16,
84}
85
86#[derive(Clone, Copy, Debug, Eq, PartialEq)]
88pub enum RegistryError {
89 UnknownFamily(u16),
91 UnsupportedVersion {
93 family: u16,
95 version: u16,
97 minimum: u16,
99 maximum: u16,
101 },
102 RetiredScheme(u16),
104 UnknownScheme(u16),
106}
107
108impl std::fmt::Display for RegistryError {
109 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
110 match self {
111 Self::UnknownFamily(family) => write!(formatter, "unknown format family {family}"),
112 Self::UnsupportedVersion {
113 family,
114 version,
115 minimum,
116 maximum,
117 } => write!(
118 formatter,
119 "format family {family} version {version} is outside accepted range {minimum}..={maximum}"
120 ),
121 Self::RetiredScheme(scheme) => {
122 write!(
123 formatter,
124 "quantization scheme id {scheme} is permanently retired"
125 )
126 }
127 Self::UnknownScheme(scheme) => {
128 write!(formatter, "unknown quantization scheme {scheme}")
129 }
130 }
131 }
132}
133
134impl std::error::Error for RegistryError {}
135
136pub struct FormatRegistry;
138
139const FAMILIES: [FamilySpec; 16] = [
140 FamilySpec {
141 family: FormatFamily::Frame,
142 current_version: 1,
143 minimum_accepted_version: 1,
144 maximum_accepted_version: 1,
145 },
146 FamilySpec {
147 family: FormatFamily::Segment,
148 current_version: 1,
149 minimum_accepted_version: 1,
150 maximum_accepted_version: 1,
151 },
152 FamilySpec {
153 family: FormatFamily::VectorCodes,
154 current_version: 1,
155 minimum_accepted_version: 1,
156 maximum_accepted_version: 1,
157 },
158 FamilySpec {
159 family: FormatFamily::VectorFactors,
160 current_version: 1,
161 minimum_accepted_version: 1,
162 maximum_accepted_version: 1,
163 },
164 FamilySpec {
165 family: FormatFamily::VectorRescore,
166 current_version: 1,
167 minimum_accepted_version: 1,
168 maximum_accepted_version: 1,
169 },
170 FamilySpec {
171 family: FormatFamily::Columns,
172 current_version: 1,
173 minimum_accepted_version: 1,
174 maximum_accepted_version: 1,
175 },
176 FamilySpec {
177 family: FormatFamily::Alive,
178 current_version: 1,
179 minimum_accepted_version: 1,
180 maximum_accepted_version: 1,
181 },
182 FamilySpec {
183 family: FormatFamily::Postings,
184 current_version: 1,
185 minimum_accepted_version: 1,
186 maximum_accepted_version: 1,
187 },
188 FamilySpec {
189 family: FormatFamily::ChecksumTable,
190 current_version: 1,
191 minimum_accepted_version: 1,
192 maximum_accepted_version: 1,
193 },
194 FamilySpec {
195 family: FormatFamily::Manifest,
196 current_version: 2,
197 minimum_accepted_version: 2,
198 maximum_accepted_version: 2,
199 },
200 FamilySpec {
201 family: FormatFamily::Wal,
202 current_version: 1,
203 minimum_accepted_version: 1,
204 maximum_accepted_version: 1,
205 },
206 FamilySpec {
207 family: FormatFamily::GraphNodeBlocks,
208 current_version: 1,
209 minimum_accepted_version: 1,
210 maximum_accepted_version: 1,
211 },
212 FamilySpec {
213 family: FormatFamily::DocumentVersions,
214 current_version: 1,
215 minimum_accepted_version: 1,
216 maximum_accepted_version: 1,
217 },
218 FamilySpec {
219 family: FormatFamily::StoredMetadata,
220 current_version: 1,
221 minimum_accepted_version: 1,
222 maximum_accepted_version: 1,
223 },
224 FamilySpec {
225 family: FormatFamily::PurgeIntent,
226 current_version: 1,
227 minimum_accepted_version: 1,
228 maximum_accepted_version: 1,
229 },
230 FamilySpec {
231 family: FormatFamily::StoredText,
232 current_version: 1,
233 minimum_accepted_version: 1,
234 maximum_accepted_version: 1,
235 },
236];
237
238impl FormatRegistry {
239 #[must_use]
241 pub const fn families() -> &'static [FamilySpec] {
242 &FAMILIES
243 }
244
245 pub fn require(family: u16, version: u16) -> Result<&'static FamilySpec, RegistryError> {
247 let spec = FAMILIES
248 .iter()
249 .find(|candidate| candidate.family.id() == family)
250 .ok_or(RegistryError::UnknownFamily(family))?;
251 if version < spec.minimum_accepted_version || version > spec.maximum_accepted_version {
252 return Err(RegistryError::UnsupportedVersion {
253 family,
254 version,
255 minimum: spec.minimum_accepted_version,
256 maximum: spec.maximum_accepted_version,
257 });
258 }
259 Ok(spec)
260 }
261
262 pub const fn require_scheme(scheme: u16) -> Result<(), RegistryError> {
264 match scheme {
265 0 | 1 | 2 | 4 => Ok(()),
266 3 | 5 => Err(RegistryError::RetiredScheme(scheme)),
267 _ => Err(RegistryError::UnknownScheme(scheme)),
268 }
269 }
270}