diff --git a/cozo_parser/src/lib.rs b/cozo_parser/src/lib.rs index 60f8683e..62d22e68 100644 --- a/cozo_parser/src/lib.rs +++ b/cozo_parser/src/lib.rs @@ -2,13 +2,8 @@ extern crate pest; #[macro_use] extern crate pest_derive; -use std::array::from_mut; -use std::borrow::Cow; -use std::cmp::{min, Ordering}; -use std::collections::HashMap; -use std::io; -use std::io::{Cursor, Read, Write}; -use ordered_float::OrderedFloat; +pub mod value; + use pest::Parser; @@ -16,409 +11,11 @@ use pest::Parser; #[grammar = "cozo.pest"] pub struct CozoParser; -#[derive(Copy, Clone)] -pub enum EdgeDir { - FwdEdge, - BwdEdge, -} - -pub enum Value<'a> { - Null, - Bool(bool), - EdgeDir(EdgeDir), - UInt(u64), - Int(i64), - Float(f64), - String(Cow<'a, str>), - List(Vec>), - Dict(HashMap, Value<'a>>), -} - -pub fn compare_keys(a: &[u8], b: &[u8]) -> Ordering { - let cur_a = &mut Cursor::new(a); - let cur_b = &mut Cursor::new(b); - - - match parse_varint(cur_a).unwrap().cmp(&parse_varint(cur_b).unwrap()) { - Ordering::Equal => { - compare_data(cur_a, cur_b) - } - x => x - } -} - -fn compare_data(cur_a: &mut T, cur_b: &mut T) -> Ordering { - loop { - let atag = parse_varint(cur_a); - let btag = parse_varint(cur_b); - match (atag, btag) { - (Err(_), Err(_)) => { - return Ordering::Equal; - } - (Err(_), Ok(_)) => { - return Ordering::Less; - } - (Ok(_), Err(_)) => { - return Ordering::Greater; - } - (Ok(atype), Ok(btype)) => { - match atype.cmp(&btype) { - Ordering::Equal => { - match ValueTag::from(atype) { - ValueTag::Int => { - match parse_zigzag(cur_a).unwrap().cmp(&parse_zigzag(cur_b).unwrap()) { - Ordering::Equal => {} - x => { return x; } - } - } - ValueTag::Float => { - let av = parse_float(cur_a).unwrap(); - let bv = parse_float(cur_b).unwrap(); - - match OrderedFloat(av).cmp(&OrderedFloat(bv)) { - Ordering::Equal => {} - x => { return x; } - } - } - ValueTag::String => { - let al = parse_varint(cur_a).unwrap(); - let bl = parse_varint(cur_b).unwrap(); - for _ in 0..min(al, bl) { - let mut av = 0; - let mut bv = 0; - cur_a.read_exact(from_mut(&mut av)).unwrap(); - cur_b.read_exact(from_mut(&mut bv)).unwrap(); - match av.cmp(&bv) { - Ordering::Equal => {} - x => { return x; } - } - } - match al.cmp(&bl) { - Ordering::Equal => {} - x => { return x; } - } - } - ValueTag::UInt => { - match parse_varint(cur_a).unwrap().cmp(&parse_varint(cur_b).unwrap()) { - Ordering::Equal => {} - x => { return x; } - } - } - ValueTag::List => { - let al = parse_varint(cur_a).unwrap(); - let bl = parse_varint(cur_b).unwrap(); - for _ in 0..min(al, bl) { - match compare_data(cur_a, cur_b) { - Ordering::Equal => {} - x => { return x; } - } - } - } - ValueTag::Dict => { - let al = parse_varint(cur_a).unwrap(); - let bl = parse_varint(cur_b).unwrap(); - for _ in 0..min(al, bl) { - let asl = parse_varint(cur_a).unwrap(); - let bsl = parse_varint(cur_b).unwrap(); - for _ in 0..min(asl, bsl) { - let mut av = 0; - let mut bv = 0; - cur_a.read_exact(from_mut(&mut av)).unwrap(); - cur_b.read_exact(from_mut(&mut bv)).unwrap(); - match av.cmp(&bv) { - Ordering::Equal => {} - x => { return x; } - } - } - match al.cmp(&bl) { - Ordering::Equal => {} - x => { return x; } - } - - match compare_data(cur_a, cur_b) { - Ordering::Equal => {} - x => { return x; } - } - } - } - // Fall through - ValueTag::Null => {} - ValueTag::BoolTrue => {} - ValueTag::BoolFalse => {} - ValueTag::FwdEdge => {} - ValueTag::BwdEdge => {} - } - } - x => { return x; } - } - } - } - } -} - -impl<'a> Value<'a> { - pub fn to_owned(&self) -> Value<'_> { - match self { - Value::Null => { - Value::Null - } - Value::Bool(b) => { - Value::Bool(*b) - } - Value::EdgeDir(dir) => { - Value::EdgeDir(*dir) - } - Value::UInt(u) => { - Value::UInt(*u) - } - Value::Int(i) => { - Value::Int(*i) - } - Value::Float(f) => { - Value::Float(*f) - } - Value::String(s) => { - Value::String(s.to_owned()) - } - Value::List(l) => { - return Value::List(l.iter().map(|v| v.to_owned()).collect()); - } - Value::Dict(d) => { - return Value::Dict(d.iter().map(|(k, v)| (k.to_owned(), v.to_owned())).collect()); - } - } - } -} - - -#[repr(u8)] -enum ValueTag { - Null = 0, - BoolTrue = 2, - BoolFalse = 4, - FwdEdge = 6, - BwdEdge = 8, - Int = 11, - Float = 13, - String = 15, - UInt = 21, - List = 101, - Dict = 103, -} - -impl From for ValueTag { - fn from(u: u64) -> Self { - match u { - u if u == ValueTag::Null as u64 => ValueTag::Null, - u if u == ValueTag::BoolTrue as u64 => ValueTag::BoolTrue, - u if u == ValueTag::BoolFalse as u64 => ValueTag::BoolFalse, - u if u == ValueTag::FwdEdge as u64 => ValueTag::FwdEdge, - u if u == ValueTag::BwdEdge as u64 => ValueTag::BwdEdge, - u if u == ValueTag::Int as u64 => ValueTag::Int, - u if u == ValueTag::Float as u64 => ValueTag::Float, - u if u == ValueTag::String as u64 => ValueTag::String, - u if u == ValueTag::UInt as u64 => ValueTag::UInt, - u if u == ValueTag::List as u64 => ValueTag::List, - u if u == ValueTag::Dict as u64 => ValueTag::Dict, - _ => { - panic!() - } - } - } -} - -pub struct CozoRawKey<'a> { - pub table_id: u64, - pub values: Vec>, -} - -pub fn build_values(vals: &[Value]) -> Vec { - let mut ret = vec![]; - ret.reserve(vals.len() * 4); - for v in vals { - build_value(&mut ret, v); - } - ret -} - -pub fn build_keys(k: &CozoRawKey) -> Vec { - let mut ret = vec![]; - ret.reserve(1 + k.values.len() * 4); - build_varint(k.table_id, &mut ret); - for v in &k.values { - build_value(&mut ret, v); - } - ret -} - -fn build_value(ret: &mut T, val: &Value) { - match val { - Value::Null => { - ret.write_all(&[ValueTag::Null as u8]).unwrap(); - } - Value::Bool(b) => { - ret.write_all(&[if *b { ValueTag::BoolTrue } else { ValueTag::BoolFalse } - as u8]).unwrap(); - } - Value::EdgeDir(dir) => { - ret.write_all(&[match *dir { - EdgeDir::FwdEdge => { - ValueTag::FwdEdge - } - EdgeDir::BwdEdge => { - ValueTag::BwdEdge - } - } as u8]).unwrap(); - } - Value::UInt(u) => { - ret.write_all(&[ValueTag::UInt as u8]).unwrap(); - build_varint(*u, ret); - } - Value::Int(i) => { - ret.write_all(&[ValueTag::Int as u8]).unwrap(); - build_zigzag(*i, ret); - } - Value::Float(f) => { - ret.write_all(&[ValueTag::Float as u8]).unwrap(); - ret.write_all(&f.to_be_bytes()).unwrap(); - } - Value::String(s) => { - ret.write_all(&[ValueTag::String as u8]).unwrap(); - let s_bytes = s.as_bytes(); - build_varint(s_bytes.len() as u64, ret); - ret.write_all(s_bytes).unwrap(); - } - Value::List(l) => { - ret.write_all(&[ValueTag::List as u8]).unwrap(); - build_varint(l.len() as u64, ret); - for v in l { - build_value(ret, v); - } - } - Value::Dict(d) => { - ret.write_all(&[ValueTag::Dict as u8]).unwrap(); - build_varint(d.len() as u64, ret); - for (k, v) in d { - let buf = k.as_bytes(); - build_varint(buf.len() as u64, ret); - ret.write_all(buf).unwrap(); - build_value(ret, v); - } - } - } -} - -fn build_varint(mut u: u64, out: &mut T) { - while u > 0b01111111 { - out.write_all(&[0b10000000 | (u as u8 & 0b01111111)]).unwrap(); - u >>= 7; - } - out.write_all(&[u as u8]).unwrap(); -} - -fn parse_varint(inp: &mut T) -> io::Result { - let mut u: u64 = 0; - let mut buf = 0u8; - let mut shift = 0; - loop { - inp.read_exact(from_mut(&mut buf))?; - u |= ((buf & 0b01111111) as u64) << shift; - if buf & 0b10000000 == 0 { - break; - } - shift += 7; - } - Ok(u) -} - -fn build_zigzag(i: i64, out: &mut T) { - let u: u64 = if i >= 0 { - (i as u64) << 1 - } else { - // Convoluted, to prevent overflow when calling .abs() - (((i + 1).abs() as u64) << 1) + 1 - }; - build_varint(u, out) -} - -fn parse_zigzag(inp: &mut T) -> io::Result { - let u = parse_varint(inp)?; - Ok(if u & 1 == 0 { - (u >> 1) as i64 - } else { - -((u >> 1) as i64) - 1 - }) -} - -fn parse_float(inp: &mut T) -> io::Result { - let mut buf = [0; 8]; - inp.read_exact(&mut buf)?; - Ok(f64::from_be_bytes(buf)) -} #[cfg(test)] mod tests { - use std::io::Cursor; use super::*; - #[test] - fn varint() { - for u in 126..(2u64).pow(9) { - let mut x = vec![]; - build_varint(u, &mut x); - let mut cur = Cursor::new(&x); - let u2 = parse_varint(&mut cur).unwrap(); - assert_eq!(u, u2); - } - - let u = u64::MIN; - let mut x = vec![]; - build_varint(u, &mut x); - let mut cur = Cursor::new(&x); - let u2 = parse_varint(&mut cur).unwrap(); - assert_eq!(u, u2); - - let u = u64::MAX; - let mut x = vec![]; - build_varint(u, &mut x); - let mut cur = Cursor::new(&x); - let u2 = parse_varint(&mut cur).unwrap(); - assert_eq!(u, u2); - } - - #[test] - fn zigzag() { - for i in 126..(2i64).pow(9) { - let mut x = vec![]; - build_zigzag(i, &mut x); - let mut cur = Cursor::new(&x); - let i2 = parse_zigzag(&mut cur).unwrap(); - assert_eq!(i, i2); - } - for i in 126..(2i64).pow(9) { - let i = -i; - let mut x = vec![]; - build_zigzag(i, &mut x); - let mut cur = Cursor::new(&x); - let i2 = parse_zigzag(&mut cur).unwrap(); - assert_eq!(i, i2); - } - - let i = i64::MIN; - let mut x = vec![]; - build_zigzag(i, &mut x); - let mut cur = Cursor::new(&x); - let i2 = parse_zigzag(&mut cur).unwrap(); - assert_eq!(i, i2); - - let i = i64::MAX; - let mut x = vec![]; - build_zigzag(i, &mut x); - let mut cur = Cursor::new(&x); - let i2 = parse_zigzag(&mut cur).unwrap(); - assert_eq!(i, i2); - } - #[test] fn identifiers() { assert_eq!(CozoParser::parse(Rule::normal_ident, "x").unwrap().as_str(), "x"); diff --git a/cozo_parser/src/value.rs b/cozo_parser/src/value.rs new file mode 100644 index 00000000..ca213d98 --- /dev/null +++ b/cozo_parser/src/value.rs @@ -0,0 +1,495 @@ +use std::borrow::Cow; +use std::cmp::{min, Ordering}; +use std::collections::HashMap; +use std::io::{Write}; +use ordered_float::OrderedFloat; + +#[repr(u8)] +#[derive(Ord, PartialOrd, Eq, PartialEq)] +pub enum ValueTag { + Null = 0, + BoolTrue = 2, + BoolFalse = 4, + FwdEdge = 6, + BwdEdge = 8, + Int = 11, + Float = 13, + String = 15, + UInt = 21, + List = 101, + Dict = 103, +} + +impl From for ValueTag { + fn from(u: u64) -> Self { + match u { + u if u == ValueTag::Null as u64 => ValueTag::Null, + u if u == ValueTag::BoolTrue as u64 => ValueTag::BoolTrue, + u if u == ValueTag::BoolFalse as u64 => ValueTag::BoolFalse, + u if u == ValueTag::FwdEdge as u64 => ValueTag::FwdEdge, + u if u == ValueTag::BwdEdge as u64 => ValueTag::BwdEdge, + u if u == ValueTag::Int as u64 => ValueTag::Int, + u if u == ValueTag::Float as u64 => ValueTag::Float, + u if u == ValueTag::String as u64 => ValueTag::String, + u if u == ValueTag::UInt as u64 => ValueTag::UInt, + u if u == ValueTag::List as u64 => ValueTag::List, + u if u == ValueTag::Dict as u64 => ValueTag::Dict, + _ => { + panic!() + } + } + } +} + + +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum EdgeDir { + FwdEdge, + BwdEdge, +} + +#[derive(Debug, PartialEq)] +pub enum Value<'a> { + Null, + Bool(bool), + EdgeDir(EdgeDir), + UInt(u64), + Int(i64), + Float(f64), + String(Cow<'a, str>), + List(Vec>), + Dict(HashMap, Value<'a>>), +} + +pub struct ByteArrayParser<'a> { + bytes: &'a [u8], + current: usize, +} + +pub struct ByteArrayBuilder { + byte_writer: T, +} + +impl<'a> ByteArrayParser<'a> { + pub fn new(bytes: &'a [u8]) -> Self { + Self { bytes, current: 0 } + } + + fn advance(&mut self, n: usize) -> Option<&'a [u8]> { + let cur = self.current; + if n + cur > self.bytes.len() { + None + } else { + self.current += n; + Some(&self.bytes[cur..cur + n]) + } + } + fn at_end(&self) -> bool { + self.current == self.bytes.len() + } + pub fn parse_varint(&mut self) -> Option { + let mut u: u64 = 0; + let mut shift = 0; + loop { + let buf = self.advance(1)?[0]; + u |= ((buf & 0b01111111) as u64) << shift; + if buf & 0b10000000 == 0 { + break; + } + shift += 7; + } + Some(u) + } + + pub fn compare_varint(&mut self, other: &mut Self) -> Ordering { + self.parse_varint().unwrap().cmp(&other.parse_varint().unwrap()) + } + pub fn parse_zigzag(&mut self) -> Option { + let u = self.parse_varint()?; + Some(if u & 1 == 0 { + (u >> 1) as i64 + } else { + -((u >> 1) as i64) - 1 + }) + } + pub fn compare_zigzag(&mut self, other: &mut Self) -> Ordering { + self.parse_zigzag().unwrap().cmp(&other.parse_zigzag().unwrap()) + } + pub fn parse_float(&mut self) -> Option { + let buf = self.advance(8)?; + let buf: [u8; 8] = buf.try_into().unwrap(); + Some(f64::from_be_bytes(buf)) + } + pub fn compare_float(&mut self, other: &mut Self) -> Ordering { + OrderedFloat(self.parse_float().unwrap()).cmp(&OrderedFloat(other.parse_float().unwrap())) + } + pub fn parse_string(&mut self) -> Option<&'a str> { + let l = self.parse_varint()?; + let bytes = self.advance(l as usize)?; + unsafe { + Some(std::str::from_utf8_unchecked(bytes)) + } + } + pub fn compare_string(&mut self, other: &mut Self) -> Ordering { + let len_a = self.parse_varint().unwrap(); + let len_b = self.parse_varint().unwrap(); + for _ in 0..min(len_a, len_b) { + let byte_a = self.advance(1).unwrap()[0]; + let byte_b = other.advance(1).unwrap()[0]; + match byte_a.cmp(&byte_b) { + Ordering::Less => { return Ordering::Less; } + Ordering::Greater => { return Ordering::Greater; } + Ordering::Equal => {} + } + } + len_a.cmp(&len_b) + } + pub fn parse_list(&mut self) -> Option>> { + let l = self.parse_varint()?; + let mut ret = Vec::with_capacity(l as usize); + for _ in 0..l { + let val = self.parse_value()?; + ret.push(val); + } + Some(ret) + } + pub fn parse_value(&mut self) -> Option> { + let tag_id = self.parse_varint()?; + match ValueTag::from(tag_id) { + ValueTag::Null => { + Some(Value::Null) + } + ValueTag::BoolTrue => { + Some(Value::Bool(true)) + } + ValueTag::BoolFalse => { + Some(Value::Bool(false)) + } + ValueTag::FwdEdge => { + Some(Value::EdgeDir(EdgeDir::FwdEdge)) + } + ValueTag::BwdEdge => { + Some(Value::EdgeDir(EdgeDir::BwdEdge)) + } + ValueTag::Int => { + Some(Value::Int(self.parse_zigzag()?)) + } + ValueTag::Float => { + Some(Value::Float(self.parse_float()?)) + } + ValueTag::String => { + Some(Value::String(Cow::from(self.parse_string()?))) + } + ValueTag::UInt => { + Some(Value::UInt(self.parse_varint()?)) + } + ValueTag::List => { + Some(Value::List(self.parse_list()?)) + } + ValueTag::Dict => { + Some(Value::Dict(self.parse_dict()?)) + } + } + } + pub fn compare_value(&mut self, other: &mut Self) -> Ordering { + match (self.parse_varint(), other.parse_varint()) { + (None, None) => { return Ordering::Equal; } + (None, Some(_)) => { return Ordering::Less; } + (Some(_), None) => { return Ordering::Greater; } + (Some(ta), Some(tb)) => { + let type_a = ValueTag::from(ta); + let type_b = ValueTag::from(tb); + match type_a.cmp(&type_b) { + Ordering::Less => { return Ordering::Less; } + Ordering::Greater => { return Ordering::Greater; } + Ordering::Equal => {} + } + match type_a { + ValueTag::Int => { self.compare_zigzag(other) } + ValueTag::Float => { self.compare_float(other) } + ValueTag::String => { self.compare_string(other) } + ValueTag::UInt => { self.compare_varint(other) } + ValueTag::List => { self.compare_list(other) } + ValueTag::Dict => { self.compare_dict(other) } + ValueTag::Null => { Ordering::Equal } + ValueTag::BoolTrue => { Ordering::Equal } + ValueTag::BoolFalse => { Ordering::Equal } + ValueTag::FwdEdge => { Ordering::Equal } + ValueTag::BwdEdge => { Ordering::Equal } + } + } + } + } + pub fn compare_list(&mut self, other: &mut Self) -> Ordering { + let len_a = self.parse_varint().unwrap(); + let len_b = self.parse_varint().unwrap(); + for _ in 0..min(len_a, len_b) { + match self.compare_value(other) { + Ordering::Less => { return Ordering::Less; } + Ordering::Greater => { return Ordering::Greater; } + Ordering::Equal => {} + } + } + len_a.cmp(&len_b) + } + pub fn parse_dict(&mut self) -> Option, Value<'a>>> { + let l = self.parse_varint()?; + let mut ret = HashMap::with_capacity(l as usize); + + for _ in 0..l { + let key = Cow::from(self.parse_string()?); + let val = self.parse_value()?; + ret.insert(key, val); + } + Some(ret) + } + pub fn compare_dict(&mut self, other: &mut Self) -> Ordering { + let len_a = self.parse_varint().unwrap(); + let len_b = self.parse_varint().unwrap(); + for _ in 0..min(len_a, len_b) { + match self.compare_string(other) { + Ordering::Less => { return Ordering::Less; } + Ordering::Greater => { return Ordering::Greater; } + Ordering::Equal => {} + } + match self.compare_value(other) { + Ordering::Less => { return Ordering::Less; } + Ordering::Greater => { return Ordering::Greater; } + Ordering::Equal => {} + } + } + len_a.cmp(&len_b) + } +} + +impl ByteArrayBuilder { + pub fn new(byte_writer: T) -> Self { + Self { byte_writer } + } + pub fn build_varint(&mut self, u: u64) { + let mut u = u; + while u > 0b01111111 { + self.byte_writer.write_all(&[0b10000000 | (u as u8 & 0b01111111)]).unwrap(); + u >>= 7; + } + self.byte_writer.write_all(&[u as u8]).unwrap(); + } + pub fn build_zigzag(&mut self, i: i64) { + let u: u64 = if i >= 0 { + (i as u64) << 1 + } else { + // Convoluted, to prevent overflow when calling .abs() + (((i + 1).abs() as u64) << 1) + 1 + }; + self.build_varint(u); + } + pub fn build_float(&mut self, f: f64) { + self.byte_writer.write_all(&f.to_be_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(); + } + pub fn build_tag(&mut self, t: ValueTag) { + self.byte_writer.write_all(&[t as u8]).unwrap(); + } + pub fn build_value(&mut self, v: &Value) { + match v { + Value::Null => { + self.build_tag(ValueTag::Null) + } + Value::Bool(b) => { + self.build_tag(if *b { ValueTag::BoolTrue } else { ValueTag::BoolFalse }) + } + Value::EdgeDir(e) => { + self.build_tag(match e { + EdgeDir::FwdEdge => { ValueTag::FwdEdge } + EdgeDir::BwdEdge => { ValueTag::BwdEdge } + }) + } + Value::UInt(u) => { + self.build_tag(ValueTag::UInt); + self.build_varint(*u); + } + Value::Int(i) => { + self.build_tag(ValueTag::Int); + self.build_zigzag(*i); + } + Value::Float(f) => { + self.build_tag(ValueTag::Float); + self.build_float(*f); + } + Value::String(s) => { + self.build_tag(ValueTag::String); + self.build_string(s); + } + Value::List(l) => { + self.build_tag(ValueTag::List); + self.build_list(l); + } + Value::Dict(d) => { + self.build_tag(ValueTag::Dict); + self.build_dict(d); + } + } + } + pub fn build_list(&mut self, l: &[Value]) { + self.build_varint(l.len() as u64); + for el in l { + self.build_value(el); + } + } + pub fn build_dict(&mut self, d: &HashMap, Value>) { + self.build_varint(d.len() as u64); + for (k, v) in d { + self.build_string(k); + self.build_value(v); + } + } +} + +pub fn cmp_keys<'a>(pa: &mut ByteArrayParser<'a>, pb: &mut ByteArrayParser<'a>) -> Ordering { + match pa.compare_varint(pb) { + Ordering::Less => { return Ordering::Less; } + Ordering::Greater => { return Ordering::Greater; } + Ordering::Equal => {} + } + cmp_data(pa, pb) +} + +pub fn cmp_data<'a>(pa: &mut ByteArrayParser<'a>, pb: &mut ByteArrayParser<'a>) -> Ordering { + loop { + match (pa.at_end(), pb.at_end()) { + (true, true) => { return Ordering::Equal; } + (true, false) => { return Ordering::Less; } + (false, true) => { return Ordering::Greater; } + (false, false) => {} + } + match pa.compare_value(pb) { + Ordering::Less => { return Ordering::Less; } + Ordering::Greater => { return Ordering::Greater; } + Ordering::Equal => {} + } + } +} + + +impl<'a> Value<'a> { + pub fn into_owned(self) -> Value<'static> { + match self { + Value::Null => { + Value::Null + } + Value::Bool(b) => { + Value::Bool(b) + } + Value::EdgeDir(dir) => { + Value::EdgeDir(dir) + } + Value::UInt(u) => { + Value::UInt(u) + } + Value::Int(i) => { + Value::Int(i) + } + Value::Float(f) => { + Value::Float(f) + } + Value::String(s) => { + Value::String(Cow::from(s.into_owned())) + } + Value::List(l) => { + let mut inner = Vec::with_capacity(l.len()); + + for el in l { + inner.push(el.into_owned()) + } + Value::List(inner) + } + Value::Dict(d) => { + let mut inner = HashMap::with_capacity(d.len()); + for (k, v) in d { + let new_k = Cow::from(k.into_owned()); + inner.insert(new_k, v.into_owned()); + } + Value::Dict(inner) + } + } + } +} + + +pub struct CozoKey<'a> { + pub table_id: u64, + pub values: Vec>, +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn varint() { + for u in 126..(2u64).pow(9) { + let mut x = vec![]; + let mut builder = ByteArrayBuilder::new(&mut x); + builder.build_varint(u); + let mut parser = ByteArrayParser::new(&x); + let u2 = parser.parse_varint().unwrap(); + assert_eq!(u, u2); + } + + let u = u64::MIN; + let mut x = vec![]; + let mut builder = ByteArrayBuilder::new(&mut x); + builder.build_varint(u); + let mut parser = ByteArrayParser::new(&x); + let u2 = parser.parse_varint().unwrap(); + assert_eq!(u, u2); + + let u = u64::MAX; + let mut x = vec![]; + let mut builder = ByteArrayBuilder::new(&mut x); + builder.build_varint(u); + let mut parser = ByteArrayParser::new(&x); + let u2 = parser.parse_varint().unwrap(); + assert_eq!(u, u2); + } + + #[test] + fn zigzag() { + for i in 126..(2i64).pow(9) { + let mut x = vec![]; + let mut builder = ByteArrayBuilder::new(&mut x); + builder.build_zigzag(i); + let mut parser = ByteArrayParser::new(&x); + let i2 = parser.parse_zigzag().unwrap(); + assert_eq!(i, i2); + } + for i in 126..(2i64).pow(9) { + let i = -i; + let mut x = vec![]; + let mut builder = ByteArrayBuilder::new(&mut x); + builder.build_zigzag(i); + let mut parser = ByteArrayParser::new(&x); + let i2 = parser.parse_zigzag().unwrap(); + assert_eq!(i, i2); + } + + let i = i64::MIN; + let mut x = vec![]; + let mut builder = ByteArrayBuilder::new(&mut x); + builder.build_zigzag(i); + let mut parser = ByteArrayParser::new(&x); + let i2 = parser.parse_zigzag().unwrap(); + assert_eq!(i, i2); + + let i = i64::MAX; + let mut x = vec![]; + let mut builder = ByteArrayBuilder::new(&mut x); + builder.build_zigzag(i); + let mut parser = ByteArrayParser::new(&x); + let i2 = parser.parse_zigzag().unwrap(); + assert_eq!(i, i2); + } +}