feat: Introduce the Number type

This commit is contained in:
Clément Renault 2019-02-11 16:58:44 +01:00
parent 83cd071827
commit db6210c7ee
No known key found for this signature in database
GPG Key ID: 0151CDAB43460DAE
7 changed files with 135 additions and 29 deletions

View File

@ -8,13 +8,13 @@ use std::path::{Path, PathBuf};
use std::sync::atomic::{AtomicBool, Ordering};
use std::ops::{Deref, DerefMut};
use crossbeam::atomic::ArcCell;
use log::{info, error, warn};
use rocksdb::rocksdb::{Writable, Snapshot};
use rocksdb::rocksdb_options::{DBOptions, ColumnFamilyOptions};
use rocksdb::rocksdb::{Writable, Snapshot};
use rocksdb::{DB, MergeOperands};
use crossbeam::atomic::ArcCell;
use lockfree::map::Map;
use hashbrown::HashMap;
use log::{info, error, warn};
pub use self::document_key::{DocumentKey, DocumentKeyAttr};
pub use self::view::{DatabaseView, DocumentIter};
@ -22,8 +22,9 @@ pub use self::update::Update;
pub use self::serde::SerializerError;
pub use self::schema::Schema;
pub use self::index::Index;
pub use self::number::{Number, ParseNumberError};
pub type RankedMap = HashMap<(DocumentId, SchemaAttr), i64>;
pub type RankedMap = HashMap<(DocumentId, SchemaAttr), Number>;
const DATA_INDEX: &[u8] = b"data-index";
const DATA_RANKED_MAP: &[u8] = b"data-ranked-map";
@ -31,6 +32,7 @@ const DATA_SCHEMA: &[u8] = b"data-schema";
pub mod schema;
pub(crate) mod index;
mod number;
mod document_key;
mod serde;
mod update;

98
src/database/number.rs Normal file
View File

@ -0,0 +1,98 @@
use std::cmp::Ordering;
use std::str::FromStr;
use std::fmt;
use serde_derive::{Serialize, Deserialize};
#[derive(Serialize, Deserialize)]
#[derive(Debug, Copy, Clone)]
pub enum Number {
Unsigned(u64),
Signed(i64),
Float(f64),
}
impl FromStr for Number {
type Err = ParseNumberError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
if let Ok(unsigned) = u64::from_str(s) {
return Ok(Number::Unsigned(unsigned))
}
if let Ok(signed) = i64::from_str(s) {
return Ok(Number::Signed(signed))
}
if let Ok(float) = f64::from_str(s) {
if float == 0.0 || float.is_normal() {
return Ok(Number::Float(float))
}
}
Err(ParseNumberError)
}
}
impl PartialOrd for Number {
fn partial_cmp(&self, other: &Number) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for Number {
fn cmp(&self, other: &Number) -> Ordering {
use Number::*;
match (self, other) {
(Unsigned(s), Unsigned(o)) => s.cmp(o),
(Unsigned(s), Signed(o)) => {
let s = i128::from(*s);
let o = i128::from(*o);
s.cmp(&o)
},
(Unsigned(s), Float(o)) => {
let s = *s as f64;
s.partial_cmp(&o).unwrap_or(Ordering::Equal)
},
(Signed(s), Unsigned(o)) => {
let s = i128::from(*s);
let o = i128::from(*o);
s.cmp(&o)
},
(Signed(s), Signed(o)) => s.cmp(o),
(Signed(s), Float(o)) => {
let s = *s as f64;
s.partial_cmp(o).unwrap_or(Ordering::Equal)
},
(Float(s), Unsigned(o)) => {
let o = *o as f64;
s.partial_cmp(&o).unwrap_or(Ordering::Equal)
},
(Float(s), Signed(o)) => {
let o = *o as f64;
s.partial_cmp(&o).unwrap_or(Ordering::Equal)
},
(Float(s), Float(o)) => {
s.partial_cmp(o).unwrap_or(Ordering::Equal)
},
}
}
}
impl PartialEq for Number {
fn eq(&self, other: &Number) -> bool {
self.cmp(other) == Ordering::Equal
}
}
impl Eq for Number { }
pub struct ParseNumberError;
impl fmt::Display for ParseNumberError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str("can not parse number")
}
}

View File

@ -17,7 +17,7 @@ macro_rules! forward_to_unserializable_type {
pub mod find_id;
pub mod key_to_string;
pub mod value_to_i64;
pub mod value_to_number;
pub mod serializer;
pub mod indexer_serializer;
pub mod deserializer;

View File

@ -5,7 +5,7 @@ use serde::ser;
use crate::database::serde::indexer_serializer::IndexerSerializer;
use crate::database::serde::key_to_string::KeyToStringSerializer;
use crate::database::serde::value_to_i64::ValueToI64Serializer;
use crate::database::serde::value_to_number::ValueToNumberSerializer;
use crate::database::update::DocumentUpdate;
use crate::database::serde::SerializerError;
use crate::tokenizer::TokenizerBuilder;
@ -231,8 +231,8 @@ where B: TokenizerBuilder
value.serialize(serializer)?;
}
if props.is_ranked() {
let integer = value.serialize(ValueToI64Serializer)?;
self.update.register_ranked_attribute(attr, integer)?;
let number = value.serialize(ValueToNumberSerializer)?;
self.update.register_ranked_attribute(attr, number)?;
}
}
@ -282,7 +282,7 @@ where B: TokenizerBuilder
value.serialize(serializer)?;
}
if props.is_ranked() {
let integer = value.serialize(ValueToI64Serializer)?;
let integer = value.serialize(ValueToNumberSerializer)?;
self.update.register_ranked_attribute(attr, integer)?;
}
}

View File

@ -1,12 +1,15 @@
use std::str::FromStr;
use serde::Serialize;
use serde::{ser, ser::Error};
use crate::database::serde::SerializerError;
use crate::database::Number;
pub struct ValueToI64Serializer;
pub struct ValueToNumberSerializer;
impl ser::Serializer for ValueToI64Serializer {
type Ok = i64;
impl ser::Serializer for ValueToNumberSerializer {
type Ok = Number;
type Error = SerializerError;
type SerializeSeq = ser::Impossible<Self::Ok, Self::Error>;
type SerializeTuple = ser::Impossible<Self::Ok, Self::Error>;
@ -19,46 +22,50 @@ impl ser::Serializer for ValueToI64Serializer {
forward_to_unserializable_type! {
bool => serialize_bool,
char => serialize_char,
f32 => serialize_f32,
f64 => serialize_f64,
}
fn serialize_i8(self, value: i8) -> Result<Self::Ok, Self::Error> {
Ok(i64::from(value))
Ok(Number::Signed(value as i64))
}
fn serialize_i16(self, value: i16) -> Result<Self::Ok, Self::Error> {
Ok(i64::from(value))
Ok(Number::Signed(value as i64))
}
fn serialize_i32(self, value: i32) -> Result<Self::Ok, Self::Error> {
Ok(i64::from(value))
Ok(Number::Signed(value as i64))
}
fn serialize_i64(self, value: i64) -> Result<Self::Ok, Self::Error> {
Ok(i64::from(value))
Ok(Number::Signed(value as i64))
}
fn serialize_u8(self, value: u8) -> Result<Self::Ok, Self::Error> {
Ok(i64::from(value))
Ok(Number::Unsigned(value as u64))
}
fn serialize_u16(self, value: u16) -> Result<Self::Ok, Self::Error> {
Ok(i64::from(value))
Ok(Number::Unsigned(value as u64))
}
fn serialize_u32(self, value: u32) -> Result<Self::Ok, Self::Error> {
Ok(i64::from(value))
Ok(Number::Unsigned(value as u64))
}
fn serialize_u64(self, value: u64) -> Result<Self::Ok, Self::Error> {
// Ok(i64::from(value))
unimplemented!()
Ok(Number::Unsigned(value as u64))
}
fn serialize_f32(self, value: f32) -> Result<Self::Ok, Self::Error> {
Ok(Number::Float(value as f64))
}
fn serialize_f64(self, value: f64) -> Result<Self::Ok, Self::Error> {
Ok(Number::Float(value))
}
fn serialize_str(self, value: &str) -> Result<Self::Ok, Self::Error> {
i64::from_str_radix(value, 10).map_err(SerializerError::custom)
Number::from_str(value).map_err(SerializerError::custom)
}
fn serialize_bytes(self, _v: &[u8]) -> Result<Self::Ok, Self::Error> {

View File

@ -16,8 +16,8 @@ use crate::tokenizer::TokenizerBuilder;
use crate::data::{DocIds, DocIndexes};
use crate::database::schema::Schema;
use crate::database::index::Index;
use crate::database::RankedMap;
use crate::database::{DATA_INDEX, DATA_RANKED_MAP};
use crate::database::{RankedMap, Number};
use crate::{DocumentId, DocIndex};
pub type Token = Vec<u8>; // TODO could be replaced by a SmallVec
@ -205,7 +205,7 @@ impl<'a> DocumentUpdate<'a> {
pub fn register_ranked_attribute(
&mut self,
attr: SchemaAttr,
integer: i64,
number: Number,
) -> Result<(), SerializerError>
{
use serde::ser::Error;
@ -216,7 +216,7 @@ impl<'a> DocumentUpdate<'a> {
));
}
self.inner.documents_ranked_fields.insert((self.document_id, attr), integer);
self.inner.documents_ranked_fields.insert((self.document_id, attr), number);
Ok(())
}

View File

@ -11,7 +11,6 @@ use crate::database::{retrieve_data_schema, retrieve_data_index, retrieve_data_r
use crate::database::serde::deserializer::Deserializer;
use crate::database::{DocumentKey, DocumentKeyAttr};
use crate::rank::{QueryBuilder, FilterFunc};
use crate::database::schema::SchemaAttr;
use crate::database::schema::Schema;
use crate::database::index::Index;
use crate::database::RankedMap;