Skip to main content

zvec_rust/
types.rs

1use std::fmt;
2
3/// Data type of a field in a zvec collection.
4#[derive(Debug, Clone, Copy, PartialEq, Eq)]
5#[repr(u32)]
6pub enum DataType {
7    /// Undefined or unknown type.
8    Undefined = 0,
9    /// Raw binary data (arbitrary bytes).
10    Binary = 1,
11    /// UTF-8 encoded string.
12    String = 2,
13    /// Boolean value.
14    Bool = 3,
15    /// 32-bit signed integer.
16    Int32 = 4,
17    /// 64-bit signed integer.
18    Int64 = 5,
19    /// 32-bit unsigned integer.
20    Uint32 = 6,
21    /// 64-bit unsigned integer.
22    Uint64 = 7,
23    /// 32-bit floating point (single precision).
24    Float = 8,
25    /// 64-bit floating point (double precision).
26    Double = 9,
27    /// Dense binary vector with 32-bit packing.
28    VectorBinary32 = 20,
29    /// Dense binary vector with 64-bit packing.
30    VectorBinary64 = 21,
31    /// Dense vector with 16-bit floating point elements (half precision).
32    VectorFp16 = 22,
33    /// Dense vector with 32-bit floating point elements (single precision).
34    VectorFp32 = 23,
35    /// Dense vector with 64-bit floating point elements (double precision).
36    VectorFp64 = 24,
37    /// Dense vector with 4-bit integer elements (packed, 2 values per byte).
38    VectorInt4 = 25,
39    /// Dense vector with 8-bit integer elements.
40    VectorInt8 = 26,
41    /// Dense vector with 16-bit integer elements.
42    VectorInt16 = 27,
43    /// Sparse vector with 16-bit floating point values.
44    SparseVectorFp16 = 30,
45    /// Sparse vector with 32-bit floating point values.
46    SparseVectorFp32 = 31,
47    /// Array of binary data.
48    ArrayBinary = 40,
49    /// Array of strings.
50    ArrayString = 41,
51    /// Array of booleans.
52    ArrayBool = 42,
53    /// Array of 32-bit signed integers.
54    ArrayInt32 = 43,
55    /// Array of 64-bit signed integers.
56    ArrayInt64 = 44,
57    /// Array of 32-bit unsigned integers.
58    ArrayUint32 = 45,
59    /// Array of 64-bit unsigned integers.
60    ArrayUint64 = 46,
61    /// Array of 32-bit floating point values.
62    ArrayFloat = 47,
63    /// Array of 64-bit floating point values.
64    ArrayDouble = 48,
65}
66
67impl From<u32> for DataType {
68    fn from(value: u32) -> Self {
69        match value {
70            0 => DataType::Undefined,
71            1 => DataType::Binary,
72            2 => DataType::String,
73            3 => DataType::Bool,
74            4 => DataType::Int32,
75            5 => DataType::Int64,
76            6 => DataType::Uint32,
77            7 => DataType::Uint64,
78            8 => DataType::Float,
79            9 => DataType::Double,
80            20 => DataType::VectorBinary32,
81            21 => DataType::VectorBinary64,
82            22 => DataType::VectorFp16,
83            23 => DataType::VectorFp32,
84            24 => DataType::VectorFp64,
85            25 => DataType::VectorInt4,
86            26 => DataType::VectorInt8,
87            27 => DataType::VectorInt16,
88            30 => DataType::SparseVectorFp16,
89            31 => DataType::SparseVectorFp32,
90            40 => DataType::ArrayBinary,
91            41 => DataType::ArrayString,
92            42 => DataType::ArrayBool,
93            43 => DataType::ArrayInt32,
94            44 => DataType::ArrayInt64,
95            45 => DataType::ArrayUint32,
96            46 => DataType::ArrayUint64,
97            47 => DataType::ArrayFloat,
98            48 => DataType::ArrayDouble,
99            _ => DataType::Undefined,
100        }
101    }
102}
103
104impl From<DataType> for u32 {
105    fn from(dt: DataType) -> Self {
106        dt as u32
107    }
108}
109
110impl fmt::Display for DataType {
111    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
112        write!(f, "{:?}", self)
113    }
114}
115
116/// Index type for a field.
117#[derive(Debug, Clone, Copy, PartialEq, Eq)]
118#[repr(u32)]
119pub enum IndexType {
120    /// Undefined or unknown index type.
121    Undefined = 0,
122    /// Hierarchical Navigable Small World graph index (recommended for most use cases).
123    Hnsw = 1,
124    /// Inverted File index with clustering.
125    Ivf = 2,
126    /// Flat (brute-force) index — exact search, no approximation.
127    Flat = 3,
128    /// Inverted index for scalar field filtering.
129    Invert = 10,
130    /// Full-text search index.
131    Fts = 11,
132}
133
134impl From<u32> for IndexType {
135    fn from(value: u32) -> Self {
136        match value {
137            1 => IndexType::Hnsw,
138            2 => IndexType::Ivf,
139            3 => IndexType::Flat,
140            10 => IndexType::Invert,
141            11 => IndexType::Fts,
142            _ => IndexType::Undefined,
143        }
144    }
145}
146
147impl From<IndexType> for u32 {
148    fn from(it: IndexType) -> Self {
149        it as u32
150    }
151}
152
153impl fmt::Display for IndexType {
154    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
155        write!(f, "{:?}", self)
156    }
157}
158
159/// Distance metric type for vector similarity search.
160#[derive(Debug, Clone, Copy, PartialEq, Eq)]
161#[repr(u32)]
162pub enum MetricType {
163    /// Undefined or unknown metric type.
164    Undefined = 0,
165    /// Euclidean distance (L2 norm). Smaller values indicate higher similarity.
166    L2 = 1,
167    /// Inner product. Larger values indicate higher similarity.
168    Ip = 2,
169    /// Cosine similarity. Values range from -1 to 1; closer to 1 means more similar.
170    Cosine = 3,
171    /// Maximum Inner Product Search with L2 normalization.
172    MipsL2 = 4,
173}
174
175impl From<u32> for MetricType {
176    fn from(value: u32) -> Self {
177        match value {
178            1 => MetricType::L2,
179            2 => MetricType::Ip,
180            3 => MetricType::Cosine,
181            4 => MetricType::MipsL2,
182            _ => MetricType::Undefined,
183        }
184    }
185}
186
187impl From<MetricType> for u32 {
188    fn from(mt: MetricType) -> Self {
189        mt as u32
190    }
191}
192
193impl fmt::Display for MetricType {
194    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
195        write!(f, "{:?}", self)
196    }
197}
198
199/// Quantization type for vector indexes.
200#[derive(Debug, Clone, Copy, PartialEq, Eq)]
201#[repr(u32)]
202pub enum QuantizeType {
203    /// No quantization.
204    Undefined = 0,
205    /// 16-bit floating point quantization (half precision).
206    Fp16 = 1,
207    /// 8-bit integer quantization.
208    Int8 = 2,
209    /// 4-bit integer quantization.
210    Int4 = 3,
211}
212
213impl From<u32> for QuantizeType {
214    fn from(value: u32) -> Self {
215        match value {
216            1 => QuantizeType::Fp16,
217            2 => QuantizeType::Int8,
218            3 => QuantizeType::Int4,
219            _ => QuantizeType::Undefined,
220        }
221    }
222}
223
224impl From<QuantizeType> for u32 {
225    fn from(qt: QuantizeType) -> Self {
226        qt as u32
227    }
228}
229
230impl fmt::Display for QuantizeType {
231    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
232        write!(f, "{:?}", self)
233    }
234}
235
236/// Log level for the zvec library.
237#[derive(Debug, Clone, Copy, PartialEq, Eq)]
238#[repr(u32)]
239pub enum LogLevel {
240    /// Verbose debug messages.
241    Debug = 0,
242    /// Informational messages.
243    Info = 1,
244    /// Warning messages for potentially harmful situations.
245    Warn = 2,
246    /// Error messages for failure events.
247    Error = 3,
248    /// Fatal messages indicating imminent abort.
249    Fatal = 4,
250}
251
252impl From<u32> for LogLevel {
253    fn from(value: u32) -> Self {
254        match value {
255            0 => LogLevel::Debug,
256            1 => LogLevel::Info,
257            2 => LogLevel::Warn,
258            3 => LogLevel::Error,
259            4 => LogLevel::Fatal,
260            _ => LogLevel::Debug,
261        }
262    }
263}
264
265impl From<LogLevel> for u32 {
266    fn from(ll: LogLevel) -> Self {
267        ll as u32
268    }
269}
270
271impl fmt::Display for LogLevel {
272    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
273        write!(f, "{:?}", self)
274    }
275}
276
277/// Document operation type.
278#[derive(Debug, Clone, Copy, PartialEq, Eq)]
279#[repr(u32)]
280pub enum DocOperator {
281    /// Insert a new document (fails if primary key already exists).
282    Insert = 0,
283    /// Update an existing document (fails if primary key does not exist).
284    Update = 1,
285    /// Insert or update a document (creates if not exists, updates if exists).
286    Upsert = 2,
287    /// Delete a document by primary key.
288    Delete = 3,
289}
290
291impl From<u32> for DocOperator {
292    fn from(value: u32) -> Self {
293        match value {
294            0 => DocOperator::Insert,
295            1 => DocOperator::Update,
296            2 => DocOperator::Upsert,
297            3 => DocOperator::Delete,
298            _ => DocOperator::Insert,
299        }
300    }
301}
302
303impl From<DocOperator> for u32 {
304    fn from(op: DocOperator) -> Self {
305        op as u32
306    }
307}
308
309impl fmt::Display for DocOperator {
310    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
311        write!(f, "{:?}", self)
312    }
313}
314
315#[cfg(test)]
316mod tests {
317    use super::*;
318
319    // =========================================================================
320    // DataType tests
321    // =========================================================================
322
323    #[test]
324    fn data_type_from_u32_scalar_types() {
325        assert_eq!(DataType::from(0), DataType::Undefined);
326        assert_eq!(DataType::from(1), DataType::Binary);
327        assert_eq!(DataType::from(2), DataType::String);
328        assert_eq!(DataType::from(3), DataType::Bool);
329        assert_eq!(DataType::from(4), DataType::Int32);
330        assert_eq!(DataType::from(5), DataType::Int64);
331        assert_eq!(DataType::from(6), DataType::Uint32);
332        assert_eq!(DataType::from(7), DataType::Uint64);
333        assert_eq!(DataType::from(8), DataType::Float);
334        assert_eq!(DataType::from(9), DataType::Double);
335    }
336
337    #[test]
338    fn data_type_from_u32_vector_types() {
339        assert_eq!(DataType::from(20), DataType::VectorBinary32);
340        assert_eq!(DataType::from(21), DataType::VectorBinary64);
341        assert_eq!(DataType::from(22), DataType::VectorFp16);
342        assert_eq!(DataType::from(23), DataType::VectorFp32);
343        assert_eq!(DataType::from(24), DataType::VectorFp64);
344        assert_eq!(DataType::from(25), DataType::VectorInt4);
345        assert_eq!(DataType::from(26), DataType::VectorInt8);
346        assert_eq!(DataType::from(27), DataType::VectorInt16);
347    }
348
349    #[test]
350    fn data_type_from_u32_sparse_vector_types() {
351        assert_eq!(DataType::from(30), DataType::SparseVectorFp16);
352        assert_eq!(DataType::from(31), DataType::SparseVectorFp32);
353    }
354
355    #[test]
356    fn data_type_from_u32_array_types() {
357        assert_eq!(DataType::from(40), DataType::ArrayBinary);
358        assert_eq!(DataType::from(41), DataType::ArrayString);
359        assert_eq!(DataType::from(42), DataType::ArrayBool);
360        assert_eq!(DataType::from(43), DataType::ArrayInt32);
361        assert_eq!(DataType::from(44), DataType::ArrayInt64);
362        assert_eq!(DataType::from(45), DataType::ArrayUint32);
363        assert_eq!(DataType::from(46), DataType::ArrayUint64);
364        assert_eq!(DataType::from(47), DataType::ArrayFloat);
365        assert_eq!(DataType::from(48), DataType::ArrayDouble);
366    }
367
368    #[test]
369    fn data_type_from_u32_unknown_falls_back_to_undefined() {
370        assert_eq!(DataType::from(10), DataType::Undefined);
371        assert_eq!(DataType::from(19), DataType::Undefined);
372        assert_eq!(DataType::from(100), DataType::Undefined);
373        assert_eq!(DataType::from(u32::MAX), DataType::Undefined);
374    }
375
376    #[test]
377    fn data_type_roundtrip() {
378        let all_types = [
379            DataType::Undefined,
380            DataType::Binary,
381            DataType::String,
382            DataType::Bool,
383            DataType::Int32,
384            DataType::Int64,
385            DataType::Uint32,
386            DataType::Uint64,
387            DataType::Float,
388            DataType::Double,
389            DataType::VectorFp32,
390            DataType::VectorFp64,
391            DataType::VectorFp16,
392            DataType::VectorInt4,
393            DataType::VectorInt8,
394            DataType::VectorInt16,
395            DataType::VectorBinary32,
396            DataType::VectorBinary64,
397            DataType::SparseVectorFp16,
398            DataType::SparseVectorFp32,
399            DataType::ArrayBinary,
400            DataType::ArrayString,
401            DataType::ArrayBool,
402            DataType::ArrayInt32,
403            DataType::ArrayInt64,
404            DataType::ArrayUint32,
405            DataType::ArrayUint64,
406            DataType::ArrayFloat,
407            DataType::ArrayDouble,
408        ];
409        for dt in all_types {
410            let numeric: u32 = dt.into();
411            let back = DataType::from(numeric);
412            assert_eq!(
413                back, dt,
414                "roundtrip failed for {:?} (numeric={})",
415                dt, numeric
416            );
417        }
418    }
419
420    #[test]
421    fn data_type_display() {
422        assert_eq!(DataType::VectorFp32.to_string(), "VectorFp32");
423        assert_eq!(DataType::String.to_string(), "String");
424        assert_eq!(DataType::Undefined.to_string(), "Undefined");
425    }
426
427    // =========================================================================
428    // IndexType tests
429    // =========================================================================
430
431    #[test]
432    fn index_type_from_u32() {
433        assert_eq!(IndexType::from(0), IndexType::Undefined);
434        assert_eq!(IndexType::from(1), IndexType::Hnsw);
435        assert_eq!(IndexType::from(2), IndexType::Ivf);
436        assert_eq!(IndexType::from(3), IndexType::Flat);
437        assert_eq!(IndexType::from(10), IndexType::Invert);
438    }
439
440    #[test]
441    fn index_type_from_u32_unknown() {
442        assert_eq!(IndexType::from(4), IndexType::Undefined);
443        assert_eq!(IndexType::from(99), IndexType::Undefined);
444    }
445
446    #[test]
447    fn index_type_roundtrip() {
448        let all = [
449            IndexType::Undefined,
450            IndexType::Hnsw,
451            IndexType::Ivf,
452            IndexType::Flat,
453            IndexType::Invert,
454        ];
455        for it in all {
456            let numeric: u32 = it.into();
457            let back = IndexType::from(numeric);
458            assert_eq!(back, it);
459        }
460    }
461
462    #[test]
463    fn index_type_display() {
464        assert_eq!(IndexType::Hnsw.to_string(), "Hnsw");
465        assert_eq!(IndexType::Flat.to_string(), "Flat");
466    }
467
468    // =========================================================================
469    // MetricType tests
470    // =========================================================================
471
472    #[test]
473    fn metric_type_from_u32() {
474        assert_eq!(MetricType::from(0), MetricType::Undefined);
475        assert_eq!(MetricType::from(1), MetricType::L2);
476        assert_eq!(MetricType::from(2), MetricType::Ip);
477        assert_eq!(MetricType::from(3), MetricType::Cosine);
478        assert_eq!(MetricType::from(4), MetricType::MipsL2);
479    }
480
481    #[test]
482    fn metric_type_from_u32_unknown() {
483        assert_eq!(MetricType::from(5), MetricType::Undefined);
484        assert_eq!(MetricType::from(99), MetricType::Undefined);
485    }
486
487    #[test]
488    fn metric_type_roundtrip() {
489        let all = [
490            MetricType::Undefined,
491            MetricType::L2,
492            MetricType::Ip,
493            MetricType::Cosine,
494            MetricType::MipsL2,
495        ];
496        for mt in all {
497            let numeric: u32 = mt.into();
498            let back = MetricType::from(numeric);
499            assert_eq!(back, mt);
500        }
501    }
502
503    #[test]
504    fn metric_type_display() {
505        assert_eq!(MetricType::Cosine.to_string(), "Cosine");
506        assert_eq!(MetricType::L2.to_string(), "L2");
507    }
508
509    // =========================================================================
510    // QuantizeType tests
511    // =========================================================================
512
513    #[test]
514    fn quantize_type_from_u32() {
515        assert_eq!(QuantizeType::from(0), QuantizeType::Undefined);
516        assert_eq!(QuantizeType::from(1), QuantizeType::Fp16);
517        assert_eq!(QuantizeType::from(2), QuantizeType::Int8);
518        assert_eq!(QuantizeType::from(3), QuantizeType::Int4);
519    }
520
521    #[test]
522    fn quantize_type_from_u32_unknown() {
523        assert_eq!(QuantizeType::from(4), QuantizeType::Undefined);
524        assert_eq!(QuantizeType::from(99), QuantizeType::Undefined);
525    }
526
527    #[test]
528    fn quantize_type_roundtrip() {
529        let all = [
530            QuantizeType::Undefined,
531            QuantizeType::Fp16,
532            QuantizeType::Int8,
533            QuantizeType::Int4,
534        ];
535        for qt in all {
536            let numeric: u32 = qt.into();
537            let back = QuantizeType::from(numeric);
538            assert_eq!(back, qt);
539        }
540    }
541
542    #[test]
543    fn quantize_type_display() {
544        assert_eq!(QuantizeType::Fp16.to_string(), "Fp16");
545        assert_eq!(QuantizeType::Int4.to_string(), "Int4");
546    }
547
548    // =========================================================================
549    // LogLevel tests
550    // =========================================================================
551
552    #[test]
553    fn log_level_from_u32() {
554        assert_eq!(LogLevel::from(0), LogLevel::Debug);
555        assert_eq!(LogLevel::from(1), LogLevel::Info);
556        assert_eq!(LogLevel::from(2), LogLevel::Warn);
557        assert_eq!(LogLevel::from(3), LogLevel::Error);
558        assert_eq!(LogLevel::from(4), LogLevel::Fatal);
559    }
560
561    #[test]
562    fn log_level_from_u32_unknown_defaults_to_debug() {
563        assert_eq!(LogLevel::from(5), LogLevel::Debug);
564        assert_eq!(LogLevel::from(99), LogLevel::Debug);
565    }
566
567    #[test]
568    fn log_level_roundtrip() {
569        let all = [
570            LogLevel::Debug,
571            LogLevel::Info,
572            LogLevel::Warn,
573            LogLevel::Error,
574            LogLevel::Fatal,
575        ];
576        for ll in all {
577            let numeric: u32 = ll.into();
578            let back = LogLevel::from(numeric);
579            assert_eq!(back, ll);
580        }
581    }
582
583    #[test]
584    fn log_level_display() {
585        assert_eq!(LogLevel::Info.to_string(), "Info");
586        assert_eq!(LogLevel::Error.to_string(), "Error");
587    }
588
589    // =========================================================================
590    // DocOperator tests
591    // =========================================================================
592
593    #[test]
594    fn doc_operator_from_u32() {
595        assert_eq!(DocOperator::from(0), DocOperator::Insert);
596        assert_eq!(DocOperator::from(1), DocOperator::Update);
597        assert_eq!(DocOperator::from(2), DocOperator::Upsert);
598        assert_eq!(DocOperator::from(3), DocOperator::Delete);
599    }
600
601    #[test]
602    fn doc_operator_from_u32_unknown_defaults_to_insert() {
603        assert_eq!(DocOperator::from(4), DocOperator::Insert);
604        assert_eq!(DocOperator::from(99), DocOperator::Insert);
605    }
606
607    #[test]
608    fn doc_operator_roundtrip() {
609        let all = [
610            DocOperator::Insert,
611            DocOperator::Update,
612            DocOperator::Upsert,
613            DocOperator::Delete,
614        ];
615        for op in all {
616            let numeric: u32 = op.into();
617            let back = DocOperator::from(numeric);
618            assert_eq!(back, op);
619        }
620    }
621
622    #[test]
623    fn doc_operator_display() {
624        assert_eq!(DocOperator::Insert.to_string(), "Insert");
625        assert_eq!(DocOperator::Delete.to_string(), "Delete");
626    }
627
628    // =========================================================================
629    // Cross-cutting tests
630    // =========================================================================
631
632    #[test]
633    fn all_enums_implement_copy() {
634        let dt = DataType::VectorFp32;
635        let dt2 = dt;
636        assert_eq!(dt, dt2);
637
638        let it = IndexType::Hnsw;
639        let it2 = it;
640        assert_eq!(it, it2);
641
642        let mt = MetricType::Cosine;
643        let mt2 = mt;
644        assert_eq!(mt, mt2);
645
646        let qt = QuantizeType::Int8;
647        let qt2 = qt;
648        assert_eq!(qt, qt2);
649
650        let ll = LogLevel::Info;
651        let ll2 = ll;
652        assert_eq!(ll, ll2);
653
654        let op = DocOperator::Upsert;
655        let op2 = op;
656        assert_eq!(op, op2);
657    }
658
659    #[test]
660    fn all_enums_implement_debug() {
661        assert_eq!(format!("{:?}", DataType::VectorFp32), "VectorFp32");
662        assert_eq!(format!("{:?}", IndexType::Hnsw), "Hnsw");
663        assert_eq!(format!("{:?}", MetricType::Cosine), "Cosine");
664        assert_eq!(format!("{:?}", QuantizeType::Int8), "Int8");
665        assert_eq!(format!("{:?}", LogLevel::Warn), "Warn");
666        assert_eq!(format!("{:?}", DocOperator::Delete), "Delete");
667    }
668
669    #[test]
670    fn repr_u32_values_match_discriminants() {
671        assert_eq!(DataType::VectorFp32 as u32, 23);
672        assert_eq!(IndexType::Hnsw as u32, 1);
673        assert_eq!(IndexType::Invert as u32, 10);
674        assert_eq!(MetricType::Cosine as u32, 3);
675        assert_eq!(QuantizeType::Int8 as u32, 2);
676        assert_eq!(LogLevel::Fatal as u32, 4);
677        assert_eq!(DocOperator::Delete as u32, 3);
678    }
679}