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