summaryrefslogtreecommitdiffstats
path: root/src/schema/value.rs
diff options
context:
space:
mode:
authorfdb-hiroshima <35889323+fdb-hiroshima@users.noreply.github.com>2019-07-27 10:57:33 +0200
committerPaul Masurel <paul.masurel@gmail.com>2019-07-27 17:57:33 +0900
commit6eb4e08636f48091f7783d52c84ef78e7ff1ada4 (patch)
tree2a91b898c007abfdf32e4261950a8625bc2749ca /src/schema/value.rs
parentc3231ca252da192e7e164b9b7474a6b99b85d7a7 (diff)
add support for float (#603)
* add basic support for float as for i64, they are mapped to u64 for indexing query parser don't work yet * Update value.rs * implement support for float in query parser * Update README.md
Diffstat (limited to 'src/schema/value.rs')
-rw-r--r--src/schema/value.rs81
1 files changed, 73 insertions, 8 deletions
diff --git a/src/schema/value.rs b/src/schema/value.rs
index bb576e9..0f3209d 100644
--- a/src/schema/value.rs
+++ b/src/schema/value.rs
@@ -2,11 +2,11 @@ use crate::schema::Facet;
use crate::DateTime;
use serde::de::Visitor;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
-use std::fmt;
+use std::{fmt, cmp::Ordering};
/// Value represents the value of a any field.
/// It is an enum over all over all of the possible field type.
-#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
+#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub enum Value {
/// The str type is used for any text information.
Str(String),
@@ -14,6 +14,8 @@ pub enum Value {
U64(u64),
/// Signed 64-bits Integer `i64`
I64(i64),
+ /// 64-bits Float `f64`
+ F64(f64),
/// Signed 64-bits Date time stamp `date`
Date(DateTime),
/// Hierarchical Facet
@@ -22,6 +24,40 @@ pub enum Value {
Bytes(Vec<u8>),
}
+impl Eq for Value {}
+impl Ord for Value {
+ fn cmp(&self, other: &Self) -> Ordering {
+ match (self,other) {
+ (Value::Str(l), Value::Str(r)) => l.cmp(r),
+ (Value::U64(l), Value::U64(r)) => l.cmp(r),
+ (Value::I64(l), Value::I64(r)) => l.cmp(r),
+ (Value::Date(l), Value::Date(r)) => l.cmp(r),
+ (Value::Facet(l), Value::Facet(r)) => l.cmp(r),
+ (Value::Bytes(l), Value::Bytes(r)) => l.cmp(r),
+ (Value::F64(l), Value::F64(r)) => {
+ match (l.is_nan(),r.is_nan()) {
+ (false, false) => l.partial_cmp(r).unwrap(), // only fail on NaN
+ (true, true) => Ordering::Equal,
+ (true, false) => Ordering::Less, // we define NaN as less than -∞
+ (false, true) => Ordering::Greater,
+ }
+ }
+ (Value::Str(_), _) => Ordering::Less,
+ (_, Value::Str(_)) => Ordering::Greater,
+ (Value::U64(_), _) => Ordering::Less,
+ (_, Value::U64(_)) => Ordering::Greater,
+ (Value::I64(_), _) => Ordering::Less,
+ (_, Value::I64(_)) => Ordering::Greater,
+ (Value::F64(_), _) => Ordering::Less,
+ (_, Value::F64(_)) => Ordering::Greater,
+ (Value::Date(_), _) => Ordering::Less,
+ (_, Value::Date(_)) => Ordering::Greater,
+ (Value::Facet(_), _) => Ordering::Less,
+ (_, Value::Facet(_)) => Ordering::Greater,
+ }
+ }
+}
+
impl Serialize for Value {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
@@ -31,6 +67,7 @@ impl Serialize for Value {
Value::Str(ref v) => serializer.serialize_str(v),
Value::U64(u) => serializer.serialize_u64(u),
Value::I64(u) => serializer.serialize_i64(u),
+ Value::F64(u) => serializer.serialize_f64(u),
Value::Date(ref date) => serializer.serialize_i64(date.timestamp()),
Value::Facet(ref facet) => facet.serialize(serializer),
Value::Bytes(ref bytes) => serializer.serialize_bytes(bytes),
@@ -60,6 +97,10 @@ impl<'de> Deserialize<'de> for Value {
Ok(Value::I64(v))
}
+ fn visit_f64<E>(self, v: f64) -> Result<Self::Value, E> {
+ Ok(Value::F64(v))
+ }
+
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E> {
Ok(Value::Str(v.to_owned()))
}
@@ -75,9 +116,7 @@ impl<'de> Deserialize<'de> for Value {
impl Value {
/// Returns the text value, provided the value is of the `Str` type.
- ///
- /// # Panics
- /// If the value is not of type `Str`
+ /// (Returns None if the value is not of the `Str` type).
pub fn text(&self) -> Option<&str> {
match *self {
Value::Str(ref text) => Some(text),
@@ -92,7 +131,7 @@ impl Value {
pub fn u64_value(&self) -> u64 {
match *self {
Value::U64(ref value) => *value,
- _ => panic!("This is not a text field."),
+ _ => panic!("This is not a u64 field."),
}
}
@@ -103,10 +142,21 @@ impl Value {
pub fn i64_value(&self) -> i64 {
match *self {
Value::I64(ref value) => *value,
- _ => panic!("This is not a text field."),
+ _ => panic!("This is not a i64 field."),
}
}
+ /// Returns the f64-value, provided the value is of the `F64` type.
+ ///
+ /// # Panics
+ /// If the value is not of type `F64`
+ pub fn f64_value(&self) -> f64 {
+ match *self {
+ Value::F64(ref value) => *value,
+ _ => panic!("This is not a f64 field."),
+ }
+ }
+
/// Returns the Date-value, provided the value is of the `Date` type.
///
/// # Panics
@@ -137,6 +187,12 @@ impl From<i64> for Value {
}
}
+impl From<f64> for Value {
+ fn from(v: f64) -> Value {
+ Value::F64(v)
+ }
+}
+
impl From<DateTime> for Value {
fn from(date_time: DateTime) -> Value {
Value::Date(date_time)
@@ -163,7 +219,7 @@ impl From<Vec<u8>> for Value {
mod binary_serialize {
use super::Value;
- use crate::common::BinarySerializable;
+ use crate::common::{BinarySerializable, f64_to_u64, u64_to_f64};
use crate::schema::Facet;
use chrono::{TimeZone, Utc};
use std::io::{self, Read, Write};
@@ -174,6 +230,7 @@ mod binary_serialize {
const HIERARCHICAL_FACET_CODE: u8 = 3;
const BYTES_CODE: u8 = 4;
const DATE_CODE: u8 = 5;
+ const F64_CODE: u8 = 6;
impl BinarySerializable for Value {
fn serialize<W: Write>(&self, writer: &mut W) -> io::Result<()> {
@@ -190,6 +247,10 @@ mod binary_serialize {
I64_CODE.serialize(writer)?;
val.serialize(writer)
}
+ Value::F64(ref val) => {
+ F64_CODE.serialize(writer)?;
+ f64_to_u64(*val).serialize(writer)
+ }
Value::Date(ref val) => {
DATE_CODE.serialize(writer)?;
val.timestamp().serialize(writer)
@@ -219,6 +280,10 @@ mod binary_serialize {
let value = i64::deserialize(reader)?;
Ok(Value::I64(value))
}
+ F64_CODE => {
+ let value = u64_to_f64(u64::deserialize(reader)?);
+ Ok(Value::F64(value))
+ }
DATE_CODE => {
let timestamp = i64::deserialize(reader)?;
Ok(Value::Date(Utc.timestamp(timestamp, 0)))