value building and parsing

main
Ziyang Hu 3 years ago
parent e39a6c0969
commit ada61a5b7b

@ -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<Value<'a>>),
Dict(HashMap<Cow<'a, str>, 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<T: Read>(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<u64> 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<Value<'a>>,
}
pub fn build_values(vals: &[Value]) -> Vec<u8> {
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<u8> {
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<T: Write>(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<T: Write>(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<T: Read>(inp: &mut T) -> io::Result<u64> {
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<T: Write>(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<T: Read>(inp: &mut T) -> io::Result<i64> {
let u = parse_varint(inp)?;
Ok(if u & 1 == 0 {
(u >> 1) as i64
} else {
-((u >> 1) as i64) - 1
})
}
fn parse_float<T: Read>(inp: &mut T) -> io::Result<f64> {
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");

@ -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<u64> 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<Value<'a>>),
Dict(HashMap<Cow<'a, str>, Value<'a>>),
}
pub struct ByteArrayParser<'a> {
bytes: &'a [u8],
current: usize,
}
pub struct ByteArrayBuilder<T: Write> {
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<u64> {
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<i64> {
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<f64> {
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<Vec<Value<'a>>> {
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<Value<'a>> {
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<HashMap<Cow<'a, str>, 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 <T:Write> ByteArrayBuilder<T> {
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<Cow<str>, 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<Value<'a>>,
}
#[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);
}
}
Loading…
Cancel
Save