diff options
author | fdb-hiroshima <35889323+fdb-hiroshima@users.noreply.github.com> | 2019-07-27 10:57:33 +0200 |
---|---|---|
committer | Paul Masurel <paul.masurel@gmail.com> | 2019-07-27 17:57:33 +0900 |
commit | 6eb4e08636f48091f7783d52c84ef78e7ff1ada4 (patch) | |
tree | 2a91b898c007abfdf32e4261950a8625bc2749ca /src/schema/value.rs | |
parent | c3231ca252da192e7e164b9b7474a6b99b85d7a7 (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.rs | 81 |
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))) |