diff --git a/cozo_parser/Cargo.toml b/cozo_parser/Cargo.toml index 23397082..33f30a0d 100644 --- a/cozo_parser/Cargo.toml +++ b/cozo_parser/Cargo.toml @@ -8,4 +8,5 @@ edition = "2021" [dependencies] pest = "2.0" pest_derive = "2.0" -ordered-float = "2.10.0" \ No newline at end of file +ordered-float = "2.10.0" +uuid = "0.8" \ No newline at end of file diff --git a/cozo_parser/src/value.rs b/cozo_parser/src/value.rs index 5b21931e..ae98eca9 100644 --- a/cozo_parser/src/value.rs +++ b/cozo_parser/src/value.rs @@ -3,6 +3,7 @@ use std::cmp::{min, Ordering}; use std::collections::HashMap; use std::io::{Write}; use ordered_float::OrderedFloat; +use uuid::Uuid; #[repr(u8)] #[derive(Ord, PartialOrd, Eq, PartialEq)] @@ -15,6 +16,7 @@ pub enum ValueTag { Int = 11, Float = 13, String = 15, + Uuid = 17, UInt = 21, List = 101, Dict = 103, @@ -34,6 +36,7 @@ pub enum Value<'a> { UInt(u64), Int(i64), Float(f64), + Uuid(Uuid), String(Cow<'a, str>), List(Vec>), Dict(HashMap, Value<'a>>), @@ -89,6 +92,7 @@ impl<'a> ByteArrayParser<'a> { u if u == ValueTag::UInt as u64 => Some(ValueTag::UInt), u if u == ValueTag::List as u64 => Some(ValueTag::List), u if u == ValueTag::Dict as u64 => Some(ValueTag::Dict), + u if u == ValueTag::Uuid as u64 => Some(ValueTag::Uuid), _ => { None } @@ -113,9 +117,32 @@ impl<'a> ByteArrayParser<'a> { let buf = self.advance(8)?.try_into().ok()?; Some(f64::from_be_bytes(buf)) } + pub fn parse_uuid(&mut self) -> Option { + Uuid::from_slice(self.advance(16)?).ok() + } pub fn compare_float(&mut self, other: &mut Self) -> Ordering { OrderedFloat(self.parse_float().unwrap()).cmp(&OrderedFloat(other.parse_float().unwrap())) } + // This should first compare UUID version, then for V1, compare the timestamps + pub fn compare_uuid(&mut self, other: &mut Self) -> Ordering { + let ua = self.parse_uuid().unwrap(); + let ub = other.parse_uuid().unwrap(); + let (a3, a2, a1, a4) = ua.as_fields(); + let (b3, b2, b1, b4) = ub.as_fields(); + match a1.cmp(&b1) { + Ordering::Equal => {} + x => {return x} + } + match a2.cmp(&b2) { + Ordering::Equal => {} + x => {return x} + } + match a3.cmp(&b3) { + Ordering::Equal => {} + x => {return x} + } + a4.cmp(b4) + } pub fn parse_string(&mut self) -> Option<&'a str> { let l = self.parse_varint()?; let bytes = self.advance(l as usize)?; @@ -182,6 +209,9 @@ impl<'a> ByteArrayParser<'a> { ValueTag::Dict => { Some(Value::Dict(self.parse_dict()?)) } + ValueTag::Uuid => { + Some(Value::Uuid(self.parse_uuid()?)) + } } } pub fn compare_value(&mut self, other: &mut Self) -> Ordering { @@ -202,6 +232,7 @@ impl<'a> ByteArrayParser<'a> { ValueTag::UInt => { self.compare_varint(other) } ValueTag::List => { self.compare_list(other) } ValueTag::Dict => { self.compare_dict(other) } + ValueTag::Uuid => { self.compare_uuid(other) } ValueTag::Null => { Ordering::Equal } ValueTag::BoolTrue => { Ordering::Equal } ValueTag::BoolFalse => { Ordering::Equal } @@ -281,6 +312,9 @@ impl ByteArrayBuilder { pub fn build_float(&mut self, f: f64) { self.byte_writer.write_all(&f.to_be_bytes()).unwrap(); } + pub fn build_uuid(&mut self, u: Uuid) { + self.byte_writer.write_all(u.as_bytes()).unwrap(); + } pub fn build_string(&mut self, s: &str) { self.build_varint(s.len() as u64); self.byte_writer.write_all(s.as_bytes()).unwrap(); @@ -326,6 +360,10 @@ impl ByteArrayBuilder { self.build_tag(ValueTag::Dict); self.build_dict(d); } + Value::Uuid(u) => { + self.build_tag(ValueTag::Uuid); + self.build_uuid(*u); + } } } pub fn build_list(&mut self, l: &[Value]) { @@ -409,6 +447,9 @@ impl<'a> Value<'a> { } Value::Dict(inner) } + Value::Uuid(u) => { + Value::Uuid(u) + } } } }