1use std::cmp::Ordering;
6
7#[derive(Debug, Clone, PartialEq)]
10pub enum IndexValue {
11 I64(i64),
13 F64(f64),
15 Str(Vec<u8>),
17}
18
19impl Eq for IndexValue {}
20
21impl Ord for IndexValue {
22 fn cmp(&self, other: &Self) -> Ordering {
23 match (self, other) {
24 (IndexValue::I64(a), IndexValue::I64(b)) => a.cmp(b),
25 (IndexValue::F64(a), IndexValue::F64(b)) => a.total_cmp(b),
26 (IndexValue::Str(a), IndexValue::Str(b)) => a.cmp(b),
27 (a, b) => disc(a).cmp(&disc(b)),
31 }
32 }
33}
34
35impl PartialOrd for IndexValue {
36 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
37 Some(self.cmp(other))
38 }
39}
40
41fn disc(v: &IndexValue) -> u8 {
42 match v {
43 IndexValue::I64(_) => 0,
44 IndexValue::F64(_) => 1,
45 IndexValue::Str(_) => 2,
46 }
47}
48
49impl IndexValue {
50 pub fn coerce(ty: crate::ValType, raw: &[u8]) -> Option<IndexValue> {
53 match ty {
54 crate::ValType::Vector => None,
56 crate::ValType::I64 => std::str::from_utf8(raw)
57 .ok()?
58 .trim()
59 .parse::<i64>()
60 .ok()
61 .map(IndexValue::I64),
62 crate::ValType::F64 => {
63 let f = std::str::from_utf8(raw).ok()?.trim().parse::<f64>().ok()?;
64 if f.is_nan() {
65 return None;
66 }
67 Some(IndexValue::F64(f))
68 }
69 crate::ValType::Str => Some(IndexValue::Str(raw.to_vec())),
70 }
71 }
72
73 pub fn parse_literal(ty: crate::ValType, raw: &[u8]) -> Option<IndexValue> {
75 Self::coerce(ty, raw)
76 }
77
78 pub fn as_f64(&self) -> f64 {
81 match self {
82 IndexValue::I64(v) => *v as f64,
83 IndexValue::F64(v) => *v,
84 IndexValue::Str(_) => 0.0,
85 }
86 }
87
88 pub fn approx_bytes(&self) -> usize {
90 match self {
91 IndexValue::I64(_) | IndexValue::F64(_) => 8,
92 IndexValue::Str(s) => s.len(),
93 }
94 }
95}