ordering and comparator

main
Ziyang Hu 2 years ago
parent 4fe24d9573
commit f675b04ed8

@ -1,2 +1,3 @@
pub mod tuple;
pub mod value;
pub mod value;
pub mod key_order;

@ -0,0 +1,62 @@
use std::cmp::Ordering;
use crate::relation::tuple::Tuple;
pub fn compare(a: &[u8], b: &[u8]) -> i8 {
let ta = Tuple::new(a);
let tb = Tuple::new(b);
match ta.get_prefix().cmp(&tb.get_prefix()) {
Ordering::Less => return -1,
Ordering::Greater => return 1,
Ordering::Equal => {}
}
let mut ia = ta.iter();
let mut ib = tb.iter();
loop {
match (ia.next(), ib.next()) {
(None, None) => return 0,
(None, Some(_)) => return -1,
(Some(_), None) => return 1,
(Some(va), Some(vb)) => {
match va.cmp(&vb) {
Ordering::Less => return -1,
Ordering::Greater => return 1,
Ordering::Equal => {}
}
}
}
}
}
#[cfg(test)]
mod tests {
use std::collections::BTreeMap;
use crate::relation::key_order::compare;
use crate::relation::tuple::Tuple;
use crate::relation::value::Value;
#[test]
fn ordering() {
let mut t = Tuple::with_prefix(0);
let t2 = Tuple::with_prefix(123);
assert_eq!(compare(t.as_ref(), t.as_ref()), 0);
assert_eq!(compare(t.as_ref(), t2.as_ref()), -1);
assert_eq!(compare(t2.as_ref(), t.as_ref()), 1);
let mut t2 = Tuple::with_prefix(0);
t.push_str("aaa");
t2.push_str("aaac");
assert_eq!(compare(t.as_ref(), t2.as_ref()), -1);
let mut t2 = Tuple::with_prefix(0);
t2.push_str("aaa");
t2.push_null();
assert_eq!(compare(t.as_ref(), t2.as_ref()), -1);
t.push_null();
assert_eq!(compare(t.as_ref(), t2.as_ref()), 0);
t.push_int(-123);
t2.push_int(123);
assert_eq!(compare(t.as_ref(), t2.as_ref()), -1);
assert_eq!(compare(t.as_ref(), t.as_ref()), 0);
let vals: Value = vec![().into(), BTreeMap::new().into(), 1e23.into(), false.into(), "xxyx".into()].into();
t.push_value(&vals);
assert_eq!(compare(t.as_ref(), t.as_ref()), 0);
}
}

@ -1,6 +1,5 @@
use std::borrow::{Cow};
use std::cell::RefCell;
use std::cmp::Ordering;
use std::collections::BTreeMap;
use uuid::Uuid;
use crate::relation::value::{EdgeDir, Tag, Value};
@ -13,17 +12,28 @@ pub struct Tuple<T>
idx_cache: RefCell<Vec<usize>>,
}
impl<T> AsRef<[u8]> for Tuple<T> where T: AsRef<[u8]> {
fn as_ref(&self) -> &[u8] {
self.data.as_ref()
}
}
const PREFIX_LEN: usize = 4;
impl<T: AsRef<[u8]>> Tuple<T> {
#[inline]
fn new(data: T) -> Self {
pub fn new(data: T) -> Self {
Self {
data,
idx_cache: RefCell::new(vec![]),
}
}
#[inline]
pub fn get_prefix(&self) -> u32 {
u32::from_be_bytes(self.data.as_ref()[0..4].try_into().unwrap())
}
#[inline]
fn all_cached(&self) -> bool {
match self.idx_cache.borrow().last() {
@ -106,7 +116,7 @@ impl<T: AsRef<[u8]>> Tuple<T> {
}
}
#[inline]
pub fn parse_value_at(&self, pos: usize) -> (Value, usize) {
fn parse_value_at(&self, pos: usize) -> (Value, usize) {
let data = self.data.as_ref();
let start = pos + 1;
let (nxt, val): (usize, Value) = match Tag::from(data[pos]) {
@ -170,10 +180,31 @@ impl<T: AsRef<[u8]>> Tuple<T> {
};
(val, nxt)
}
pub fn iter(&self) -> TupleIter<T> {
TupleIter {
tuple: self,
pos: 4,
}
}
}
impl Tuple<&[u8]> {}
pub struct TupleIter<'a, T: AsRef<[u8]>> {
tuple: &'a Tuple<T>,
pos: usize,
}
impl<'a, T: AsRef<[u8]>> Iterator for TupleIter<'a, T> {
type Item = Value<'a>;
fn next(&mut self) -> Option<Self::Item> {
if self.pos == self.tuple.data.as_ref().len() {
return None;
}
let (v, pos) = self.tuple.parse_value_at(self.pos);
self.pos = pos;
Some(v)
}
}
impl Tuple<Vec<u8>> {
#[inline]
@ -246,7 +277,7 @@ impl Tuple<Vec<u8>> {
Value::EdgeDir(e) => self.push_edge_dir(*e),
Value::UInt(u) => self.push_uint(*u),
Value::Int(i) => self.push_int(*i),
Value::Float(f) => self.push_float(*f),
Value::Float(f) => self.push_float(f.into_inner()),
Value::Uuid(u) => self.push_uuid(*u),
Value::Text(t) => self.push_str(t),
Value::List(l) => {
@ -309,7 +340,6 @@ impl Tuple<Vec<u8>> {
};
self.push_varint(u);
}
}
impl<T: AsRef<[u8]>> PartialEq for Tuple<T> {
@ -321,20 +351,6 @@ impl<T: AsRef<[u8]>> PartialEq for Tuple<T> {
impl<T: AsRef<[u8]>> Eq for Tuple<T> {}
impl<T: AsRef<[u8]>> PartialOrd for Tuple<T> {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl<T: AsRef<[u8]>> Ord for Tuple<T> {
#[inline]
fn cmp(&self, other: &Self) -> Ordering {
todo!()
}
}
#[cfg(test)]
mod tests {
@ -432,5 +448,24 @@ mod tests {
assert_eq!(Value::from(-123345i64), t.get(7).unwrap());
assert_eq!(Value::from(BTreeMap::from([("yzyz".into(), "fifo".into())])), t.get(10).unwrap());
assert_eq!(None, t.get(13131));
println!("{:?}", t.iter().collect::<Vec<Value>>());
for v in t.iter() {
println!("{}", v);
}
}
/*
#[test]
fn lifetime() {
let v;
{
let s : Vec<u8> = vec![];
let s = s.as_slice();
let p = Tuple::new(s);
v = p.get(0);
}
println!("{:?}", v);
}
*/
}

@ -1,5 +1,7 @@
use std::borrow::Cow;
use std::collections::BTreeMap;
use std::fmt::{Display, Formatter, Write};
use ordered_float::OrderedFloat;
use uuid::Uuid;
#[repr(u8)]
@ -66,21 +68,21 @@ impl From<u8> for Tag {
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Ord, PartialOrd)]
pub enum EdgeDir {
Fwd,
Bwd,
}
#[derive(Debug, Clone, PartialEq)]
#[derive(Debug, Clone, PartialEq, Ord, PartialOrd, Eq)]
pub enum Value<'a> {
Null,
Bool(bool),
EdgeDir(EdgeDir),
UInt(u64),
Int(i64),
Float(f64),
Float(OrderedFloat<f64>),
Uuid(Uuid),
Text(Cow<'a, str>),
List(Vec<Value<'a>>),
@ -89,7 +91,7 @@ pub enum Value<'a> {
pub type StaticValue = Value<'static>;
impl <'a> Value<'a> {
impl<'a> Value<'a> {
#[inline]
pub fn to_static(self) -> StaticValue {
match self {
@ -147,6 +149,14 @@ impl From<i64> for StaticValue {
impl From<f64> for StaticValue {
#[inline]
fn from(f: f64) -> Self {
Value::Float(f.into())
}
}
impl From<OrderedFloat<f64>> for StaticValue {
#[inline]
fn from(f: OrderedFloat<f64>) -> Self {
Value::Float(f)
}
}
@ -185,3 +195,70 @@ impl<'a> From<BTreeMap<Cow<'a, str>, Value<'a>>> for Value<'a> {
Value::Dict(m)
}
}
impl<'a> Display for Value<'a> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Value::Null => { f.write_str("null")?; }
Value::Bool(b) => { f.write_str(if *b { "true" } else { "false" })?; }
Value::EdgeDir(d) => {
f.write_str(match d {
EdgeDir::Fwd => "fwd",
EdgeDir::Bwd => "bwd"
})?;
}
Value::UInt(u) => {
f.write_str(&u.to_string())?;
f.write_str("u")?;
}
Value::Int(i) => { f.write_str(&i.to_string())?; }
Value::Float(n) => { f.write_str(&format!("{:e}", n.into_inner()))?; }
Value::Uuid(u) => { f.write_str(&u.to_string())?; }
Value::Text(t) => {
f.write_char('"')?;
for char in t.chars() {
match char {
'"' => { f.write_str("\\\"")?; }
'\\' => { f.write_str("\\\\")?; }
'/' => { f.write_str("\\/")?; }
'\x08' => { f.write_str("\\b")?; }
'\x0c' => { f.write_str("\\f")?; }
'\n' => { f.write_str("\\n")?; }
'\r' => { f.write_str("\\r")?; }
'\t' => { f.write_str("\\t")?; }
c => { f.write_char(c)?; }
}
}
f.write_char('"')?;
}
Value::List(l) => {
f.write_char('[')?;
let mut first = true;
for v in l.iter() {
if !first {
f.write_char(',')?;
}
Display::fmt(v, f)?;
first = false;
}
f.write_char(']')?;
}
Value::Dict(d) => {
f.write_char('{')?;
let mut first = true;
for (k, v) in d.iter() {
if !first {
f.write_char(',')?;
}
Display::fmt(&Value::Text(k.clone()), f)?;
f.write_char(':')?;
Display::fmt(v, f)?;
first = false;
}
f.write_char('}')?;
}
}
Ok(())
}
}
Loading…
Cancel
Save