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