use std::cmp::Ordering;
#[derive(Debug, Clone, PartialEq)]
pub enum IndexValue {
I64(i64),
F64(f64),
Str(Vec<u8>),
}
impl Eq for IndexValue {}
impl Ord for IndexValue {
fn cmp(&self, other: &Self) -> Ordering {
match (self, other) {
(IndexValue::I64(a), IndexValue::I64(b)) => a.cmp(b),
(IndexValue::F64(a), IndexValue::F64(b)) => a.total_cmp(b),
(IndexValue::Str(a), IndexValue::Str(b)) => a.cmp(b),
(a, b) => disc(a).cmp(&disc(b)),
}
}
}
impl PartialOrd for IndexValue {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
fn disc(v: &IndexValue) -> u8 {
match v {
IndexValue::I64(_) => 0,
IndexValue::F64(_) => 1,
IndexValue::Str(_) => 2,
}
}
impl IndexValue {
pub fn coerce(ty: crate::ValType, raw: &[u8]) -> Option<IndexValue> {
match ty {
crate::ValType::Vector => None,
crate::ValType::I64 => std::str::from_utf8(raw)
.ok()?
.trim()
.parse::<i64>()
.ok()
.map(IndexValue::I64),
crate::ValType::F64 => {
let f = std::str::from_utf8(raw).ok()?.trim().parse::<f64>().ok()?;
if f.is_nan() {
return None;
}
Some(IndexValue::F64(f))
}
crate::ValType::Str => Some(IndexValue::Str(raw.to_vec())),
}
}
pub fn parse_literal(ty: crate::ValType, raw: &[u8]) -> Option<IndexValue> {
Self::coerce(ty, raw)
}
pub fn as_f64(&self) -> f64 {
match self {
IndexValue::I64(v) => *v as f64,
IndexValue::F64(v) => *v,
IndexValue::Str(_) => 0.0,
}
}
pub fn approx_bytes(&self) -> usize {
match self {
IndexValue::I64(_) | IndexValue::F64(_) => 8,
IndexValue::Str(s) => s.len(),
}
}
}