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