diff --git a/src/ast.rs b/src/ast.rs index 2538f4c8..3ecfa75c 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -1,315 +1,316 @@ -use std::sync::Arc; -use pest::iterators::{Pair}; -use pest::Parser as PestParser; -use pest::prec_climber::{Assoc, PrecClimber, Operator}; -use crate::parser::Parser; -use crate::parser::Rule; -use lazy_static::lazy_static; -use crate::ast::Expr::{Apply, Const}; -use crate::error::CozoError; -use crate::error::Result; -use crate::value::Value; - - -#[derive(PartialEq, Debug)] -pub enum Op { - Add, - Sub, - Mul, - Div, - Eq, - Neq, - Gt, - Lt, - Ge, - Le, - Neg, - Minus, - Mod, - Or, - And, - Coalesce, - Pow, - Call, - IsNull, - NotNull, -} - - -lazy_static! { - static ref PREC_CLIMBER: PrecClimber = { - use Assoc::*; - - PrecClimber::new(vec![ - Operator::new(Rule::op_or, Left), - Operator::new(Rule::op_and, Left), - Operator::new(Rule::op_gt, Left) | Operator::new(Rule::op_lt, Left) | Operator::new(Rule::op_ge,Left) | Operator::new(Rule::op_le, Left), - Operator::new(Rule::op_mod, Left), - Operator::new(Rule::op_eq, Left) | Operator::new(Rule::op_ne, Left), - Operator::new(Rule::op_add, Left) | Operator::new(Rule::op_sub, Left), - Operator::new(Rule::op_mul, Left) | Operator::new(Rule::op_div, Left), - Operator::new(Rule::op_pow, Assoc::Right), - Operator::new(Rule::op_coalesce, Assoc::Left) - ]) - }; -} - - -#[derive(PartialEq, Debug)] -pub enum Expr<'a> { - List(Vec>), - Dict(Vec, Vec>), - Apply(Op, Vec>), - Ident(String), - Const(Value<'a>), -} - -pub trait ExprVisitor<'a, T> { - fn visit_expr(&self, ex: &Expr<'a>) -> T; -} - - -fn build_expr_infix<'a>(lhs: Result>, op: Pair, rhs: Result>) -> Result> { - let lhs = lhs?; - let rhs = rhs?; - let op = match op.as_rule() { - Rule::op_add => Op::Add, - Rule::op_sub => Op::Sub, - Rule::op_mul => Op::Mul, - Rule::op_div => Op::Div, - Rule::op_eq => Op::Eq, - Rule::op_ne => Op::Neq, - Rule::op_or => Op::Or, - Rule::op_and => Op::And, - Rule::op_mod => Op::Mod, - Rule::op_gt => Op::Gt, - Rule::op_ge => Op::Ge, - Rule::op_lt => Op::Lt, - Rule::op_le => Op::Le, - Rule::op_pow => Op::Pow, - Rule::op_coalesce => Op::Coalesce, - _ => unreachable!() - }; - Ok(Apply(op, vec![lhs, rhs])) -} - -#[inline] -fn parse_int(s: &str, radix: u32) -> i64 { - i64::from_str_radix(&s[2..].replace('_', ""), radix).unwrap() -} - -#[inline] -fn parse_raw_string(pair: Pair) -> Result { - Ok(pair.into_inner().into_iter().next().unwrap().as_str().to_string()) -} - -#[inline] -fn parse_quoted_string(pair: Pair) -> Result { - let pairs = pair.into_inner().next().unwrap().into_inner(); - let mut ret = String::with_capacity(pairs.as_str().len()); - for pair in pairs { - let s = pair.as_str(); - match s { - r#"\""# => ret.push('"'), - r"\\" => ret.push('\\'), - r"\/" => ret.push('/'), - r"\b" => ret.push('\x08'), - r"\f" => ret.push('\x0c'), - r"\n" => ret.push('\n'), - r"\r" => ret.push('\r'), - r"\t" => ret.push('\t'), - s if s.starts_with(r"\u") => { - let code = parse_int(s, 16) as u32; - let ch = char::from_u32(code).ok_or(CozoError::InvalidUtfCode)?; - ret.push(ch); - } - s if s.starts_with('\\') => return Err(CozoError::InvalidEscapeSequence), - s => ret.push_str(s) - } - } - Ok(ret) -} - - -#[inline] -fn parse_s_quoted_string(pair: Pair) -> Result { - let pairs = pair.into_inner().next().unwrap().into_inner(); - let mut ret = String::with_capacity(pairs.as_str().len()); - for pair in pairs { - let s = pair.as_str(); - match s { - r#"\'"# => ret.push('\''), - r"\\" => ret.push('\\'), - r"\/" => ret.push('/'), - r"\b" => ret.push('\x08'), - r"\f" => ret.push('\x0c'), - r"\n" => ret.push('\n'), - r"\r" => ret.push('\r'), - r"\t" => ret.push('\t'), - s if s.starts_with(r"\u") => { - let code = parse_int(s, 16) as u32; - let ch = char::from_u32(code).ok_or(CozoError::InvalidUtfCode)?; - ret.push(ch); - } - s if s.starts_with('\\') => return Err(CozoError::InvalidEscapeSequence), - s => ret.push_str(s) - } - } - Ok(ret) -} - -#[inline] -pub fn parse_string(pair: Pair) -> Result { - match pair.as_rule() { - Rule::quoted_string => Ok(parse_quoted_string(pair)?), - Rule::s_quoted_string => Ok(parse_s_quoted_string(pair)?), - Rule::raw_string => Ok(parse_raw_string(pair)?), - Rule::ident => Ok(pair.as_str().to_string()), - _ => unreachable!() - } -} - -fn build_expr_primary(pair: Pair) -> Result { - match pair.as_rule() { - Rule::expr => build_expr_primary(pair.into_inner().next().unwrap()), - Rule::term => build_expr_primary(pair.into_inner().next().unwrap()), - Rule::grouping => build_expr(pair.into_inner().next().unwrap()), - - Rule::unary => { - let mut inner = pair.into_inner(); - let op = inner.next().unwrap().as_rule(); - let term = build_expr_primary(inner.next().unwrap())?; - Ok(Apply(match op { - Rule::negate => Op::Neg, - Rule::minus => Op::Minus, - _ => unreachable!() - }, vec![term])) - } - - Rule::pos_int => Ok(Const(Value::Int(pair.as_str().replace('_', "").parse::()?))), - Rule::hex_pos_int => Ok(Const(Value::Int(parse_int(pair.as_str(), 16)))), - Rule::octo_pos_int => Ok(Const(Value::Int(parse_int(pair.as_str(), 8)))), - Rule::bin_pos_int => Ok(Const(Value::Int(parse_int(pair.as_str(), 2)))), - Rule::dot_float | Rule::sci_float => Ok(Const(Value::Float(pair.as_str().replace('_', "").parse::()?))), - Rule::null => Ok(Const(Value::Null)), - Rule::boolean => Ok(Const(Value::Bool(pair.as_str() == "true"))), - Rule::quoted_string | Rule::s_quoted_string | Rule::raw_string => Ok( - Const(Value::OwnString(Arc::new(parse_string(pair)?)))), - Rule::list => { - let mut vals = vec![]; - let mut has_apply = false; - for p in pair.into_inner() { - let res = build_expr_primary(p)?; - match res { - v @ Const(_) => { vals.push(v) } - v => { - has_apply = true; - vals.push(v); - } - } - } - if has_apply { - Ok(Expr::List(vals)) - } else { - Ok(Const(Value::List(Arc::new(vals.into_iter().map(|v| { - match v { - Apply(_, _) => { unreachable!() } - Expr::List(_) => { unreachable!() } - Expr::Dict(_, _) => { unreachable!() } - Const(v) => { v } - Expr::Ident(_) => unimplemented!() - } - }).collect())))) - } - } - Rule::dict => { - // let mut res = BTreeMap::new(); - let mut keys = vec![]; - let mut vals = vec![]; - let mut has_apply = false; - for p in pair.into_inner() { - match p.as_rule() { - Rule::dict_pair => { - let mut inner = p.into_inner(); - let name = parse_string(inner.next().unwrap())?; - keys.push(name); - match build_expr_primary(inner.next().unwrap())? { - v @ Const(_) => { - vals.push(v); - } - v => { - has_apply = true; - vals.push(v); - } - } - } - _ => todo!() - } - } - if has_apply { - Ok(Expr::Dict(keys, vals)) - } else { - Ok(Const(Value::Dict(Arc::new(keys.into_iter().zip(vals.into_iter()).map(|(k, v)| { - match v { - Expr::List(_) => { unreachable!() } - Expr::Dict(_, _) => { unreachable!() } - Apply(_, _) => { unreachable!() } - Const(v) => { - (k.into(), v) - } - Expr::Ident(_) => unimplemented!() - } - }).collect())))) - } - } - Rule::param => { - Ok(Expr::Ident(pair.as_str().to_string())) - } - _ => { - println!("Unhandled rule {:?}", pair.as_rule()); - unimplemented!() - } - } -} - -pub fn build_expr(pair: Pair) -> Result { - PREC_CLIMBER.climb(pair.into_inner(), build_expr_primary, build_expr_infix) -} - -pub fn parse_expr_from_str(inp: &str) -> Result { - let expr_tree = Parser::parse(Rule::expr, inp)?.next().unwrap(); - build_expr(expr_tree) -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn raw_string() { - println!("{:#?}", parse_expr_from_str(r#####"r#"x"#"#####)) - } - - #[test] - fn parse_literals() { - assert_eq!(parse_expr_from_str("1").unwrap(), Const(Value::Int(1))); - assert_eq!(parse_expr_from_str("12_3").unwrap(), Const(Value::Int(123))); - assert_eq!(parse_expr_from_str("0xaf").unwrap(), Const(Value::Int(0xaf))); - assert_eq!(parse_expr_from_str("0xafcE_f").unwrap(), Const(Value::Int(0xafcef))); - assert_eq!(parse_expr_from_str("0o1234_567").unwrap(), Const(Value::Int(0o1234567))); - assert_eq!(parse_expr_from_str("0o0001234_567").unwrap(), Const(Value::Int(0o1234567))); - assert_eq!(parse_expr_from_str("0b101010").unwrap(), Const(Value::Int(0b101010))); - - assert_eq!(parse_expr_from_str("0.0").unwrap(), Const(Value::Float(0.))); - assert_eq!(parse_expr_from_str("10.022_3").unwrap(), Const(Value::Float(10.0223))); - assert_eq!(parse_expr_from_str("10.022_3e-100").unwrap(), Const(Value::Float(10.0223e-100))); - - assert_eq!(parse_expr_from_str("null").unwrap(), Const(Value::Null)); - assert_eq!(parse_expr_from_str("true").unwrap(), Const(Value::Bool(true))); - assert_eq!(parse_expr_from_str("false").unwrap(), Const(Value::Bool(false))); - assert_eq!(parse_expr_from_str(r#""x \n \ty \"""#).unwrap(), Const(Value::RefString("x \n \ty \""))); - assert_eq!(parse_expr_from_str(r#""x'""#).unwrap(), Const(Value::RefString("x'"))); - assert_eq!(parse_expr_from_str(r#"'"x"'"#).unwrap(), Const(Value::RefString(r##""x""##))); - assert_eq!(parse_expr_from_str(r#####"r###"x"yz"###"#####).unwrap(), Const(Value::RefString(r##"x"yz"##))); - } -} \ No newline at end of file +// use std::borrow::Cow; +// use std::sync::Arc; +// use pest::iterators::{Pair}; +// use pest::Parser as PestParser; +// use pest::prec_climber::{Assoc, PrecClimber, Operator}; +// use crate::parser::Parser; +// use crate::parser::Rule; +// use lazy_static::lazy_static; +// use crate::ast::Expr::{Apply, Const}; +// use crate::error::CozoError; +// use crate::error::Result; +// use crate::value::Value; +// +// +// #[derive(PartialEq, Debug)] +// pub enum Op { +// Add, +// Sub, +// Mul, +// Div, +// Eq, +// Neq, +// Gt, +// Lt, +// Ge, +// Le, +// Neg, +// Minus, +// Mod, +// Or, +// And, +// Coalesce, +// Pow, +// Call, +// IsNull, +// NotNull, +// } +// +// +// lazy_static! { +// static ref PREC_CLIMBER: PrecClimber = { +// use Assoc::*; +// +// PrecClimber::new(vec![ +// Operator::new(Rule::op_or, Left), +// Operator::new(Rule::op_and, Left), +// Operator::new(Rule::op_gt, Left) | Operator::new(Rule::op_lt, Left) | Operator::new(Rule::op_ge,Left) | Operator::new(Rule::op_le, Left), +// Operator::new(Rule::op_mod, Left), +// Operator::new(Rule::op_eq, Left) | Operator::new(Rule::op_ne, Left), +// Operator::new(Rule::op_add, Left) | Operator::new(Rule::op_sub, Left), +// Operator::new(Rule::op_mul, Left) | Operator::new(Rule::op_div, Left), +// Operator::new(Rule::op_pow, Assoc::Right), +// Operator::new(Rule::op_coalesce, Assoc::Left) +// ]) +// }; +// } +// +// +// #[derive(PartialEq, Debug)] +// pub enum Expr<'a> { +// List(Vec>), +// Dict(Vec, Vec>), +// Apply(Op, Vec>), +// Ident(String), +// Const(Value<'a>), +// } +// +// pub trait ExprVisitor<'a, T> { +// fn visit_expr(&self, ex: &Expr<'a>) -> T; +// } +// +// +// fn build_expr_infix<'a>(lhs: Result>, op: Pair, rhs: Result>) -> Result> { +// let lhs = lhs?; +// let rhs = rhs?; +// let op = match op.as_rule() { +// Rule::op_add => Op::Add, +// Rule::op_sub => Op::Sub, +// Rule::op_mul => Op::Mul, +// Rule::op_div => Op::Div, +// Rule::op_eq => Op::Eq, +// Rule::op_ne => Op::Neq, +// Rule::op_or => Op::Or, +// Rule::op_and => Op::And, +// Rule::op_mod => Op::Mod, +// Rule::op_gt => Op::Gt, +// Rule::op_ge => Op::Ge, +// Rule::op_lt => Op::Lt, +// Rule::op_le => Op::Le, +// Rule::op_pow => Op::Pow, +// Rule::op_coalesce => Op::Coalesce, +// _ => unreachable!() +// }; +// Ok(Apply(op, vec![lhs, rhs])) +// } +// +// #[inline] +// fn parse_int(s: &str, radix: u32) -> i64 { +// i64::from_str_radix(&s[2..].replace('_', ""), radix).unwrap() +// } +// +// #[inline] +// fn parse_raw_string(pair: Pair) -> Result { +// Ok(pair.into_inner().into_iter().next().unwrap().as_str().to_string()) +// } +// +// #[inline] +// fn parse_quoted_string(pair: Pair) -> Result { +// let pairs = pair.into_inner().next().unwrap().into_inner(); +// let mut ret = String::with_capacity(pairs.as_str().len()); +// for pair in pairs { +// let s = pair.as_str(); +// match s { +// r#"\""# => ret.push('"'), +// r"\\" => ret.push('\\'), +// r"\/" => ret.push('/'), +// r"\b" => ret.push('\x08'), +// r"\f" => ret.push('\x0c'), +// r"\n" => ret.push('\n'), +// r"\r" => ret.push('\r'), +// r"\t" => ret.push('\t'), +// s if s.starts_with(r"\u") => { +// let code = parse_int(s, 16) as u32; +// let ch = char::from_u32(code).ok_or(CozoError::InvalidUtfCode)?; +// ret.push(ch); +// } +// s if s.starts_with('\\') => return Err(CozoError::InvalidEscapeSequence), +// s => ret.push_str(s) +// } +// } +// Ok(ret) +// } +// +// +// #[inline] +// fn parse_s_quoted_string(pair: Pair) -> Result { +// let pairs = pair.into_inner().next().unwrap().into_inner(); +// let mut ret = String::with_capacity(pairs.as_str().len()); +// for pair in pairs { +// let s = pair.as_str(); +// match s { +// r#"\'"# => ret.push('\''), +// r"\\" => ret.push('\\'), +// r"\/" => ret.push('/'), +// r"\b" => ret.push('\x08'), +// r"\f" => ret.push('\x0c'), +// r"\n" => ret.push('\n'), +// r"\r" => ret.push('\r'), +// r"\t" => ret.push('\t'), +// s if s.starts_with(r"\u") => { +// let code = parse_int(s, 16) as u32; +// let ch = char::from_u32(code).ok_or(CozoError::InvalidUtfCode)?; +// ret.push(ch); +// } +// s if s.starts_with('\\') => return Err(CozoError::InvalidEscapeSequence), +// s => ret.push_str(s) +// } +// } +// Ok(ret) +// } +// +// #[inline] +// pub fn parse_string(pair: Pair) -> Result { +// match pair.as_rule() { +// Rule::quoted_string => Ok(parse_quoted_string(pair)?), +// Rule::s_quoted_string => Ok(parse_s_quoted_string(pair)?), +// Rule::raw_string => Ok(parse_raw_string(pair)?), +// Rule::ident => Ok(pair.as_str().to_string()), +// _ => unreachable!() +// } +// } +// +// fn build_expr_primary(pair: Pair) -> Result { +// match pair.as_rule() { +// Rule::expr => build_expr_primary(pair.into_inner().next().unwrap()), +// Rule::term => build_expr_primary(pair.into_inner().next().unwrap()), +// Rule::grouping => build_expr(pair.into_inner().next().unwrap()), +// +// Rule::unary => { +// let mut inner = pair.into_inner(); +// let op = inner.next().unwrap().as_rule(); +// let term = build_expr_primary(inner.next().unwrap())?; +// Ok(Apply(match op { +// Rule::negate => Op::Neg, +// Rule::minus => Op::Minus, +// _ => unreachable!() +// }, vec![term])) +// } +// +// Rule::pos_int => Ok(Const(Value::Int(pair.as_str().replace('_', "").parse::()?))), +// Rule::hex_pos_int => Ok(Const(Value::Int(parse_int(pair.as_str(), 16)))), +// Rule::octo_pos_int => Ok(Const(Value::Int(parse_int(pair.as_str(), 8)))), +// Rule::bin_pos_int => Ok(Const(Value::Int(parse_int(pair.as_str(), 2)))), +// Rule::dot_float | Rule::sci_float => Ok(Const(Value::Float(pair.as_str().replace('_', "").parse::()?))), +// Rule::null => Ok(Const(Value::Null)), +// Rule::boolean => Ok(Const(Value::Bool(pair.as_str() == "true"))), +// Rule::quoted_string | Rule::s_quoted_string | Rule::raw_string => Ok( +// Const(Value::Text(Arc::new(Cow::Owned(parse_string(pair)?))))), +// Rule::list => { +// let mut vals = vec![]; +// let mut has_apply = false; +// for p in pair.into_inner() { +// let res = build_expr_primary(p)?; +// match res { +// v @ Const(_) => { vals.push(v) } +// v => { +// has_apply = true; +// vals.push(v); +// } +// } +// } +// if has_apply { +// Ok(Expr::List(vals)) +// } else { +// Ok(Const(Value::List(Arc::new(vals.into_iter().map(|v| { +// match v { +// Apply(_, _) => { unreachable!() } +// Expr::List(_) => { unreachable!() } +// Expr::Dict(_, _) => { unreachable!() } +// Const(v) => { v } +// Expr::Ident(_) => unimplemented!() +// } +// }).collect())))) +// } +// } +// Rule::dict => { +// // let mut res = BTreeMap::new(); +// let mut keys = vec![]; +// let mut vals = vec![]; +// let mut has_apply = false; +// for p in pair.into_inner() { +// match p.as_rule() { +// Rule::dict_pair => { +// let mut inner = p.into_inner(); +// let name = parse_string(inner.next().unwrap())?; +// keys.push(name); +// match build_expr_primary(inner.next().unwrap())? { +// v @ Const(_) => { +// vals.push(v); +// } +// v => { +// has_apply = true; +// vals.push(v); +// } +// } +// } +// _ => todo!() +// } +// } +// if has_apply { +// Ok(Expr::Dict(keys, vals)) +// } else { +// Ok(Const(Value::Dict(Arc::new(keys.into_iter().zip(vals.into_iter()).map(|(k, v)| { +// match v { +// Expr::List(_) => { unreachable!() } +// Expr::Dict(_, _) => { unreachable!() } +// Apply(_, _) => { unreachable!() } +// Const(v) => { +// (k.into(), v) +// } +// Expr::Ident(_) => unimplemented!() +// } +// }).collect())))) +// } +// } +// Rule::param => { +// Ok(Expr::Ident(pair.as_str().to_string())) +// } +// _ => { +// println!("Unhandled rule {:?}", pair.as_rule()); +// unimplemented!() +// } +// } +// } +// +// pub fn build_expr(pair: Pair) -> Result { +// PREC_CLIMBER.climb(pair.into_inner(), build_expr_primary, build_expr_infix) +// } +// +// pub fn parse_expr_from_str(inp: &str) -> Result { +// let expr_tree = Parser::parse(Rule::expr, inp)?.next().unwrap(); +// build_expr(expr_tree) +// } +// +// #[cfg(test)] +// mod tests { +// use super::*; +// +// #[test] +// fn raw_string() { +// println!("{:#?}", parse_expr_from_str(r#####"r#"x"#"#####)) +// } +// +// #[test] +// fn parse_literals() { +// assert_eq!(parse_expr_from_str("1").unwrap(), Const(Value::Int(1))); +// assert_eq!(parse_expr_from_str("12_3").unwrap(), Const(Value::Int(123))); +// assert_eq!(parse_expr_from_str("0xaf").unwrap(), Const(Value::Int(0xaf))); +// assert_eq!(parse_expr_from_str("0xafcE_f").unwrap(), Const(Value::Int(0xafcef))); +// assert_eq!(parse_expr_from_str("0o1234_567").unwrap(), Const(Value::Int(0o1234567))); +// assert_eq!(parse_expr_from_str("0o0001234_567").unwrap(), Const(Value::Int(0o1234567))); +// assert_eq!(parse_expr_from_str("0b101010").unwrap(), Const(Value::Int(0b101010))); +// +// assert_eq!(parse_expr_from_str("0.0").unwrap(), Const(Value::Float(0.))); +// assert_eq!(parse_expr_from_str("10.022_3").unwrap(), Const(Value::Float(10.0223))); +// assert_eq!(parse_expr_from_str("10.022_3e-100").unwrap(), Const(Value::Float(10.0223e-100))); +// +// assert_eq!(parse_expr_from_str("null").unwrap(), Const(Value::Null)); +// assert_eq!(parse_expr_from_str("true").unwrap(), Const(Value::Bool(true))); +// assert_eq!(parse_expr_from_str("false").unwrap(), Const(Value::Bool(false))); +// assert_eq!(parse_expr_from_str(r#""x \n \ty \"""#).unwrap(), Const(Value::Text(Arc::new(Cow::Borrowed("x \n \ty \""))))); +// // assert_eq!(parse_expr_from_str(r#""x'""#).unwrap(), Const(Value::RefString("x'"))); +// // assert_eq!(parse_expr_from_str(r#"'"x"'"#).unwrap(), Const(Value::RefString(r##""x""##))); +// // assert_eq!(parse_expr_from_str(r#####"r###"x"yz"###"#####).unwrap(), Const(Value::RefString(r##"x"yz"##))); +// } +// } \ No newline at end of file diff --git a/src/definition.rs b/src/definition.rs index d6e1f93c..c66e1392 100644 --- a/src/definition.rs +++ b/src/definition.rs @@ -1,598 +1,598 @@ -use std::borrow::{Borrow, BorrowMut}; -use std::collections::BTreeMap; -use std::sync::Arc; -use pest::iterators::{Pair, Pairs}; -use crate::ast::parse_string; -use crate::env::{Env, LayeredEnv, Environment}; -use crate::error::Result; -use crate::error::CozoError::*; -use crate::eval::Evaluator; -use crate::storage::{RocksStorage}; -use crate::typing::{Col, Columns, Edge, Index, Node, StorageStatus, Structured, TableId, Typing}; -use crate::typing::StorageStatus::{Planned, Stored}; -use crate::value::{ByteArrayBuilder, ByteArrayParser, StaticValue, Value}; -use crate::parser::{Parser, Rule}; -use pest::Parser as PestParser; -use cozo_rocks::*; -// use rocksdb::IteratorMode; - -fn parse_ident(pair: Pair) -> String { - pair.as_str().to_string() -} - -pub fn build_name_in_def(pair: Pair, forbid_underscore: bool) -> Result { - let inner = pair.into_inner().next().unwrap(); - let name = match inner.as_rule() { - Rule::ident => parse_ident(inner), - Rule::raw_string | Rule::s_quoted_string | Rule::quoted_string => parse_string(inner)?, - _ => unreachable!() - }; - if forbid_underscore && name.starts_with('_') { - Err(ReservedIdent) - } else { - Ok(name) - } -} - -fn parse_col_name(pair: Pair) -> Result<(String, bool)> { - let mut pairs = pair.into_inner(); - let mut is_key = false; - let mut nxt_pair = pairs.next().unwrap(); - if nxt_pair.as_rule() == Rule::key_marker { - is_key = true; - nxt_pair = pairs.next().unwrap(); - } - - Ok((build_name_in_def(nxt_pair, true)?, is_key)) -} - - -impl Environment { - pub fn build_edge_def(&mut self, pair: Pair, local_id: usize) -> Result { - let mut inner = pair.into_inner(); - let src_name = build_name_in_def(inner.next().unwrap(), true)?; - let src = self.resolve(&src_name).ok_or(UndefinedType)?; - let src = src.borrow(); - let src_id = if let Structured::Node(n) = src { - n.id.clone() - } else { - return Err(WrongType); - }; - let name = build_name_in_def(inner.next().unwrap(), true)?; - let dst_name = build_name_in_def(inner.next().unwrap(), true)?; - let dst = self.resolve(&dst_name).ok_or(UndefinedType)?; - let dst = dst.borrow(); - let dst_id = if let Structured::Node(n) = dst { - n.id.clone() - } else { - return Err(WrongType); - }; - if local_id == 0 && (!src_id.is_global() || !dst_id.is_global()) { - return Err(IncompatibleEdge); - } - let (keys, cols) = if let Some(p) = inner.next() { - self.build_col_defs(p)? - } else { - (vec![], vec![]) - }; - let table_id = TableId { name: name.clone(), local_id }; - let edge = Edge { - status: Planned, - src: src_id, - dst: dst_id, - id: table_id.clone(), - keys, - cols, - col_map: BTreeMap::new(), - }; - if self.define_new(name.clone(), Structured::Edge(edge)) { - if let Some(Structured::Node(src)) = self.resolve_mut(&src_name) { - src.out_e.push(table_id.clone()); - } else { - unreachable!() - } - - if let Some(Structured::Node(dst)) = self.resolve_mut(&dst_name) { - dst.in_e.push(table_id); - } else { - unreachable!() - } - Ok(name) - } else { - Err(NameConflict) - } - } - pub fn build_node_def(&mut self, pair: Pair, local_id: usize) -> Result { - let mut inner = pair.into_inner(); - let name = build_name_in_def(inner.next().unwrap(), true)?; - let (keys, cols) = self.build_col_defs(inner.next().unwrap())?; - let table_id = TableId { name: name.clone(), local_id }; - let node = Node { - status: Planned, - id: table_id, - keys, - cols, - out_e: vec![], - in_e: vec![], - attached: vec![], - col_map: BTreeMap::new(), - }; - if self.define_new(name.clone(), Structured::Node(node)) { - Ok(name) - } else { - Err(NameConflict) - } - } - - fn build_col_list(&mut self, pair: Pair) -> Result> { - let mut ret = vec![]; - for p in pair.into_inner() { - ret.push(build_name_in_def(p, true)?); - } - Ok(ret) - } - fn build_columns_def(&mut self, pair: Pair, local_id: usize) -> Result { - let mut inner = pair.into_inner(); - let name = build_name_in_def(inner.next().unwrap(), true)?; - let node_name = build_name_in_def(inner.next().unwrap(), true)?; - let node = self.resolve(&node_name).ok_or(UndefinedType)?; - let node = node.borrow(); - let node_id = if let Structured::Node(n) = node { - n.id.clone() - } else if let Structured::Edge(n) = node { - n.id.clone() - } else { - return Err(WrongType); - }; - let (keys, cols) = self.build_col_defs(inner.next().unwrap())?; - if !keys.is_empty() { - return Err(UnexpectedIndexColumns); - } - let table_id = TableId { name: name.clone(), local_id }; - if table_id.is_global() && !node_id.is_global() { - return Err(IncompatibleEdge); - } - - if self.define_new(name.clone(), Structured::Columns(Columns { - status: Planned, - id: table_id, - attached: node_id, - cols, - })) { - Ok(name) - } else { - Err(NameConflict) - } - } - - fn build_index_def(&mut self, pair: Pair, local_id: usize) -> Result { - let mut inner = pair.into_inner(); - let mut name = build_name_in_def(inner.next().unwrap(), true)?; - let node_name; - let nxt = inner.next().unwrap(); - - let col_list = match nxt.as_rule() { - Rule::col_list => { - node_name = name; - name = "_".to_string() + &node_name; - let cols = self.build_col_list(nxt)?; - name.push('_'); - for col in &cols { - name.push('_'); - name += col; - } - cols - } - _ => { - node_name = build_name_in_def(nxt, true)?; - self.build_col_list(inner.next().unwrap())? - } - }; - - let node = self.resolve(&node_name).ok_or(UndefinedType)?; - let node = node.borrow(); - let node_id = if let Structured::Node(n) = node { - n.id.clone() - } else { - return Err(WrongType); - }; - let table_id = TableId { name: name.clone(), local_id }; - - if table_id.is_global() && !node_id.is_global() { - return Err(IncompatibleEdge); - } - - // TODO: make sure cols make sense - - if self.define_new(name.clone(), Structured::Index(Index { - status: Planned, - id: table_id, - attached: node_id, - cols: col_list, - })) { - Ok(name) - } else { - Err(NameConflict) - } - } - - pub fn build_type_from_str(&self, src: &str) -> Result { - let ast = Parser::parse(Rule::typing, src)?.next().unwrap(); - self.build_type(ast) - } - - fn build_type(&self, pair: Pair) -> Result { - let mut pairs = pair.into_inner(); - let mut inner = pairs.next().unwrap(); - let nullable = if Rule::nullable_marker == inner.as_rule() { - inner = pairs.next().unwrap(); - true - } else { - false - }; - let t = match inner.as_rule() { - Rule::simple_type => { - let name = parse_ident(inner.into_inner().next().unwrap()); - let typ = self.resolve(&name).ok_or(UndefinedType)?; - let typ = typ.borrow(); - if let Structured::Typing(t) = typ { - t.clone() - } else { - return Err(UndefinedType); - } - } - Rule::list_type => { - let inner_t = self.build_type(inner.into_inner().next().unwrap())?; - Typing::HList(Box::new(inner_t)) - } - // Rule::tuple_type => {}, - _ => unreachable!() - }; - Ok(if nullable { - Typing::Nullable(Box::new(t)) - } else { - t - }) - } - - fn build_default_value(&self, _pair: Pair) -> Result { - // TODO: _pair is an expression, parse it and evaluate it to a constant value - Ok(Value::Null) - } - - fn build_col_entry(&self, pair: Pair) -> Result<(Col, bool)> { - let mut pairs = pair.into_inner(); - let (name, is_key) = parse_col_name(pairs.next().unwrap())?; - let typ = self.build_type(pairs.next().unwrap())?; - let default = if let Some(p) = pairs.next() { - // TODO: check value is suitable for the type - self.build_default_value(p)? - } else { - Value::Null - }; - Ok((Col { - name, - typ, - default, - }, is_key)) - } - - fn build_col_defs(&self, pair: Pair) -> Result<(Vec, Vec)> { - let mut keys = vec![]; - let mut cols = vec![]; - for pair in pair.into_inner() { - let (col, is_key) = self.build_col_entry(pair)?; - if is_key { - keys.push(col) - } else { - cols.push(col) - } - } - - Ok((keys, cols)) - } -} - -#[repr(u8)] -pub enum TableKind { - Node = 1, - Edge = 2, - Columns = 3, - Index = 4, -} - -impl RocksStorage { - #[allow(unused_variables)] - fn all_metadata(&self) -> Result> { - let default_cf = self.db.get_cf_handle("default")?; - let it = self.db.iterator(&default_cf, None); - let mut ret = vec![]; - let env = self.root_env.write().expect("Root environment poisoned"); - while it.is_valid() { - let k = it.key(); - let v = it.value(); - let mut key_parser = ByteArrayParser::new(&k); - let mut data_parser = ByteArrayParser::new(&v); - key_parser.parse_varint().unwrap(); - let table_name = key_parser.parse_value().unwrap().get_string().unwrap().to_string(); - let table_kind = data_parser.parse_value().unwrap(); - let table_id = TableId { name: table_name, local_id: 0 }; - - match table_kind { - Value::UInt(i) if i == TableKind::Node as u64 => { - let keys: Vec<_> = data_parser.parse_value().unwrap().get_list().unwrap() - .iter().map(|v| { - let vs = v.get_list().unwrap(); - let mut vs = vs.iter(); - let name = vs.next().unwrap().get_string().unwrap().to_string(); - let typ = vs.next().unwrap().get_string().unwrap(); - let typ = env.build_type_from_str(&typ).unwrap(); - let default = vs.next().unwrap().owned_clone(); - Col { - name, - typ, - default, - } - }).collect(); - let cols: Vec<_> = data_parser.parse_value().unwrap().get_list().unwrap() - .iter().map(|v| { - let vs = v.get_list().unwrap(); - let mut vs = vs.iter(); - let name = vs.next().unwrap().get_string().unwrap().to_string(); - let typ = vs.next().unwrap().get_string().unwrap(); - let typ = env.build_type_from_str(&typ).unwrap(); - let default = vs.next().unwrap().owned_clone(); - Col { - name, - typ, - default, - } - }).collect(); - let node = Node { - status: StorageStatus::Stored, - id: table_id, - keys, - cols, - out_e: vec![], // TODO fix these - in_e: vec![], - attached: vec![], - col_map: BTreeMap::new(), - }; - ret.push(Structured::Node(node)); - } - Value::UInt(i) if i == TableKind::Edge as u64 => { - let src_name = data_parser.parse_value().unwrap().get_string().unwrap().to_string(); - let dst_name = data_parser.parse_value().unwrap().get_string().unwrap().to_string(); - let src_id = TableId { name: src_name, local_id: 0 }; - let dst_id = TableId { name: dst_name, local_id: 0 }; - let keys: Vec<_> = data_parser.parse_value().unwrap().get_list().unwrap() - .iter().map(|v| { - let vs = v.get_list().unwrap(); - let mut vs = vs.iter(); - let name = vs.next().unwrap().get_string().unwrap().to_string(); - let typ = vs.next().unwrap().get_string().unwrap(); - let typ = env.build_type_from_str(&typ).unwrap(); - let default = vs.next().unwrap().owned_clone(); - Col { - name, - typ, - default, - } - }).collect(); - let cols: Vec<_> = data_parser.parse_value().unwrap().get_list().unwrap() - .iter().map(|v| { - let vs = v.get_list().unwrap(); - let mut vs = vs.iter(); - let name = vs.next().unwrap().get_string().unwrap().to_string(); - let typ = vs.next().unwrap().get_string().unwrap(); - let typ = env.build_type_from_str(&typ).unwrap(); - let default = vs.next().unwrap().owned_clone(); - Col { - name, - typ, - default, - } - }).collect(); - let edge = Edge { - status: StorageStatus::Stored, - src: src_id, - dst: dst_id, - id: table_id, - keys, - cols, - col_map: BTreeMap::new(), - }; - ret.push(Structured::Edge(edge)); - } - Value::UInt(i) if i == TableKind::Columns as u64 => { - todo!() - } - Value::UInt(i) if i == TableKind::Index as u64 => { - todo!() - } - _ => unreachable!() - } - - it.next(); - } - Ok(ret) - } - - fn persist_node(&mut self, node: &mut Node) -> Result<()> { - let mut key_writer = ByteArrayBuilder::with_capacity(8); - key_writer.build_varint(0); - key_writer.build_value(&Value::RefString(&node.id.name)); - let mut val_writer = ByteArrayBuilder::with_capacity(128); - val_writer.build_value(&Value::UInt(TableKind::Node as u64)); - val_writer.build_value(&Value::List(Arc::new(node.keys.iter().map(|k| { - Value::List(Arc::new(vec![ - Value::RefString(&k.name), - Value::OwnString(Arc::new(format!("{}", k.typ))), - k.default.clone(), - ])) - }).collect()))); - val_writer.build_value(&Value::List(Arc::new(node.cols.iter().map(|k| { - Value::List(Arc::new(vec![ - Value::RefString(&k.name), - Value::OwnString(Arc::new(format!("{}", k.typ))), - k.default.clone(), - ])) - }).collect()))); - - self.put_global(&key_writer.get(), &val_writer.get())?; - node.status = Stored; - Ok(()) - } - - fn persist_edge(&mut self, edge: &mut Edge) -> Result<()> { - let mut key_writer = ByteArrayBuilder::with_capacity(8); - key_writer.build_varint(0); - key_writer.build_value(&Value::RefString(&edge.id.name)); - - let mut val_writer = ByteArrayBuilder::with_capacity(128); - val_writer.build_value(&Value::UInt(TableKind::Edge as u64)); - val_writer.build_value(&Value::RefString(&edge.src.name)); - val_writer.build_value(&Value::RefString(&edge.dst.name)); - val_writer.build_value(&Value::List(Arc::new(edge.keys.iter().map(|k| { - Value::List(Arc::new(vec![ - Value::RefString(&k.name), - Value::OwnString(Arc::new(format!("{}", k.typ))), - k.default.clone(), - ])) - }).collect()))); - val_writer.build_value(&Value::List(Arc::new(edge.cols.iter().map(|k| { - Value::List(Arc::new(vec![ - Value::RefString(&k.name), - Value::OwnString(Arc::new(format!("{}", k.typ))), - k.default.clone(), - ])) - }).collect()))); - - self.put_global(&key_writer.get(), &val_writer.get())?; - edge.status = Stored; - Ok(()) - } -} - -impl Evaluator { - pub fn restore_metadata(&mut self) -> Result<()> { - let mds = self.storage.all_metadata()?; - for md in &mds { - match md { - v @ Structured::Node(n) => { - // TODO: check if they are the same if one already exists - self.root_define(n.id.name.clone(), v.clone()); - } - v @ Structured::Edge(e) => { - self.root_define(e.id.name.clone(), v.clone()); - } - Structured::Columns(_) => {} - Structured::Index(_) => {} - Structured::Typing(_) => unreachable!(), - Structured::Value(_) => unreachable!() - } - } - Ok(()) - } - - // fn persist_change(&mut self, tname: &str, global: bool) -> Result<()> { - // self.storage.create_table(tname, global)?; - // let tbl = { - // self.resolve_mut(tname).unwrap() - // }; - // if global { - // match tbl { - // Structured::Node(n) => self.storage.persist_node(n), - // Structured::Edge(e) => self.storage.persist_edge(e), - // Structured::Columns(_) => unimplemented!(), - // Structured::Index(_) => unimplemented!(), - // Structured::Typing(_) => panic!(), - // Structured::Value(_) => unreachable!() - // } - // } else { - // Ok(()) - // } - // } - - - pub fn build_table(&mut self, pairs: Pairs) -> Result<()> { - let mut new_tables = vec![]; - for pair in pairs { - match pair.as_rule() { - r @ (Rule::global_def | Rule::local_def) => { - let inner = pair.into_inner().next().unwrap(); - let global = r == Rule::global_def; - let local_id = self.storage.get_next_local_id(global); - let mut env_to_build = - // if global { - // self.storage.root_env.write().expect("Root environment poisoned").borrow_mut() - // } else { - self.env_stack.last_mut().unwrap() - ; - // }; - new_tables.push((global, match inner.as_rule() { - Rule::node_def => { - env_to_build.build_node_def(inner, local_id)? - } - Rule::edge_def => { - env_to_build.build_edge_def(inner, local_id)? - } - Rule::columns_def => { - env_to_build.build_columns_def(inner, local_id)? - } - Rule::index_def => { - env_to_build.build_index_def(inner, local_id)? - } - _ => todo!() - })); - } - Rule::EOI => {} - _ => unreachable!() - } - } - for (global, tname) in &new_tables { - // self.persist_change(tname, *global).unwrap(); // TODO proper error handling - } - Ok(()) - } - - pub fn insert_data(&mut self, _pairs: Pairs, _bindings: BTreeMap<&str, Value>) -> Result<()> { - todo!() - } -} - - -#[cfg(test)] -mod tests { - use super::*; - use pest::Parser as PestParser; - use crate::eval::EvaluatorWithStorage; - use crate::parser::Parser; - - fn send_sync(_x: &X) {} - - #[test] - fn definitions() { - let s = r#" - create node "Person" { - *id: Int, - name: String, - email: ?String, - habits: ?[?String] - } - - create edge (Person)-[Friend]->(Person) { - relation: ?String - } - "#; - let parsed = Parser::parse(Rule::file, s).unwrap(); - let db = RocksStorage::new("_path_for_rocksdb_storagex".to_string()).unwrap(); - send_sync(&db); - let mut eval = EvaluatorWithStorage::new(db).unwrap(); - eval.build_table(parsed).unwrap(); - eval.restore_metadata().unwrap(); - // eval.storage.delete_storage().unwrap(); - println!("{:#?}", eval.resolve("Person")); - println!("{:#?}", eval.resolve("Friend")); - } -} \ No newline at end of file +// use std::borrow::{Borrow, BorrowMut, Cow}; +// use std::collections::BTreeMap; +// use std::sync::Arc; +// use pest::iterators::{Pair, Pairs}; +// use crate::ast::parse_string; +// use crate::env::{Env, LayeredEnv, Environment}; +// use crate::error::Result; +// use crate::error::CozoError::*; +// use crate::eval::Evaluator; +// use crate::storage::{RocksStorage}; +// use crate::typing::{Col, Columns, Edge, Index, Node, StorageStatus, Structured, TableId, Typing}; +// use crate::typing::StorageStatus::{Planned, Stored}; +// use crate::value::{ByteArrayBuilder, ByteArrayParser, StaticValue, Value}; +// use crate::parser::{Parser, Rule}; +// use pest::Parser as PestParser; +// use cozo_rocks::*; +// // use rocksdb::IteratorMode; +// +// fn parse_ident(pair: Pair) -> String { +// pair.as_str().to_string() +// } +// +// pub fn build_name_in_def(pair: Pair, forbid_underscore: bool) -> Result { +// let inner = pair.into_inner().next().unwrap(); +// let name = match inner.as_rule() { +// Rule::ident => parse_ident(inner), +// Rule::raw_string | Rule::s_quoted_string | Rule::quoted_string => parse_string(inner)?, +// _ => unreachable!() +// }; +// if forbid_underscore && name.starts_with('_') { +// Err(ReservedIdent) +// } else { +// Ok(name) +// } +// } +// +// fn parse_col_name(pair: Pair) -> Result<(String, bool)> { +// let mut pairs = pair.into_inner(); +// let mut is_key = false; +// let mut nxt_pair = pairs.next().unwrap(); +// if nxt_pair.as_rule() == Rule::key_marker { +// is_key = true; +// nxt_pair = pairs.next().unwrap(); +// } +// +// Ok((build_name_in_def(nxt_pair, true)?, is_key)) +// } +// +// +// impl Environment { +// pub fn build_edge_def(&mut self, pair: Pair, local_id: usize) -> Result { +// let mut inner = pair.into_inner(); +// let src_name = build_name_in_def(inner.next().unwrap(), true)?; +// let src = self.resolve(&src_name).ok_or(UndefinedType)?; +// let src = src.borrow(); +// let src_id = if let Structured::Node(n) = src { +// n.id.clone() +// } else { +// return Err(WrongType); +// }; +// let name = build_name_in_def(inner.next().unwrap(), true)?; +// let dst_name = build_name_in_def(inner.next().unwrap(), true)?; +// let dst = self.resolve(&dst_name).ok_or(UndefinedType)?; +// let dst = dst.borrow(); +// let dst_id = if let Structured::Node(n) = dst { +// n.id.clone() +// } else { +// return Err(WrongType); +// }; +// if local_id == 0 && (!src_id.is_global() || !dst_id.is_global()) { +// return Err(IncompatibleEdge); +// } +// let (keys, cols) = if let Some(p) = inner.next() { +// self.build_col_defs(p)? +// } else { +// (vec![], vec![]) +// }; +// let table_id = TableId { name: name.clone(), local_id }; +// let edge = Edge { +// status: Planned, +// src: src_id, +// dst: dst_id, +// id: table_id.clone(), +// keys, +// cols, +// col_map: BTreeMap::new(), +// }; +// if self.define_new(name.clone(), Structured::Edge(edge)) { +// if let Some(Structured::Node(src)) = self.resolve_mut(&src_name) { +// src.out_e.push(table_id.clone()); +// } else { +// unreachable!() +// } +// +// if let Some(Structured::Node(dst)) = self.resolve_mut(&dst_name) { +// dst.in_e.push(table_id); +// } else { +// unreachable!() +// } +// Ok(name) +// } else { +// Err(NameConflict) +// } +// } +// pub fn build_node_def(&mut self, pair: Pair, local_id: usize) -> Result { +// let mut inner = pair.into_inner(); +// let name = build_name_in_def(inner.next().unwrap(), true)?; +// let (keys, cols) = self.build_col_defs(inner.next().unwrap())?; +// let table_id = TableId { name: name.clone(), local_id }; +// let node = Node { +// status: Planned, +// id: table_id, +// keys, +// cols, +// out_e: vec![], +// in_e: vec![], +// attached: vec![], +// col_map: BTreeMap::new(), +// }; +// if self.define_new(name.clone(), Structured::Node(node)) { +// Ok(name) +// } else { +// Err(NameConflict) +// } +// } +// +// fn build_col_list(&mut self, pair: Pair) -> Result> { +// let mut ret = vec![]; +// for p in pair.into_inner() { +// ret.push(build_name_in_def(p, true)?); +// } +// Ok(ret) +// } +// fn build_columns_def(&mut self, pair: Pair, local_id: usize) -> Result { +// let mut inner = pair.into_inner(); +// let name = build_name_in_def(inner.next().unwrap(), true)?; +// let node_name = build_name_in_def(inner.next().unwrap(), true)?; +// let node = self.resolve(&node_name).ok_or(UndefinedType)?; +// let node = node.borrow(); +// let node_id = if let Structured::Node(n) = node { +// n.id.clone() +// } else if let Structured::Edge(n) = node { +// n.id.clone() +// } else { +// return Err(WrongType); +// }; +// let (keys, cols) = self.build_col_defs(inner.next().unwrap())?; +// if !keys.is_empty() { +// return Err(UnexpectedIndexColumns); +// } +// let table_id = TableId { name: name.clone(), local_id }; +// if table_id.is_global() && !node_id.is_global() { +// return Err(IncompatibleEdge); +// } +// +// if self.define_new(name.clone(), Structured::Columns(Columns { +// status: Planned, +// id: table_id, +// attached: node_id, +// cols, +// })) { +// Ok(name) +// } else { +// Err(NameConflict) +// } +// } +// +// fn build_index_def(&mut self, pair: Pair, local_id: usize) -> Result { +// let mut inner = pair.into_inner(); +// let mut name = build_name_in_def(inner.next().unwrap(), true)?; +// let node_name; +// let nxt = inner.next().unwrap(); +// +// let col_list = match nxt.as_rule() { +// Rule::col_list => { +// node_name = name; +// name = "_".to_string() + &node_name; +// let cols = self.build_col_list(nxt)?; +// name.push('_'); +// for col in &cols { +// name.push('_'); +// name += col; +// } +// cols +// } +// _ => { +// node_name = build_name_in_def(nxt, true)?; +// self.build_col_list(inner.next().unwrap())? +// } +// }; +// +// let node = self.resolve(&node_name).ok_or(UndefinedType)?; +// let node = node.borrow(); +// let node_id = if let Structured::Node(n) = node { +// n.id.clone() +// } else { +// return Err(WrongType); +// }; +// let table_id = TableId { name: name.clone(), local_id }; +// +// if table_id.is_global() && !node_id.is_global() { +// return Err(IncompatibleEdge); +// } +// +// // TODO: make sure cols make sense +// +// if self.define_new(name.clone(), Structured::Index(Index { +// status: Planned, +// id: table_id, +// attached: node_id, +// cols: col_list, +// })) { +// Ok(name) +// } else { +// Err(NameConflict) +// } +// } +// +// pub fn build_type_from_str(&self, src: &str) -> Result { +// let ast = Parser::parse(Rule::typing, src)?.next().unwrap(); +// self.build_type(ast) +// } +// +// fn build_type(&self, pair: Pair) -> Result { +// let mut pairs = pair.into_inner(); +// let mut inner = pairs.next().unwrap(); +// let nullable = if Rule::nullable_marker == inner.as_rule() { +// inner = pairs.next().unwrap(); +// true +// } else { +// false +// }; +// let t = match inner.as_rule() { +// Rule::simple_type => { +// let name = parse_ident(inner.into_inner().next().unwrap()); +// let typ = self.resolve(&name).ok_or(UndefinedType)?; +// let typ = typ.borrow(); +// if let Structured::Typing(t) = typ { +// t.clone() +// } else { +// return Err(UndefinedType); +// } +// } +// Rule::list_type => { +// let inner_t = self.build_type(inner.into_inner().next().unwrap())?; +// Typing::HList(Box::new(inner_t)) +// } +// // Rule::tuple_type => {}, +// _ => unreachable!() +// }; +// Ok(if nullable { +// Typing::Nullable(Box::new(t)) +// } else { +// t +// }) +// } +// +// fn build_default_value(&self, _pair: Pair) -> Result { +// // TODO: _pair is an expression, parse it and evaluate it to a constant value +// Ok(Value::Null) +// } +// +// fn build_col_entry(&self, pair: Pair) -> Result<(Col, bool)> { +// let mut pairs = pair.into_inner(); +// let (name, is_key) = parse_col_name(pairs.next().unwrap())?; +// let typ = self.build_type(pairs.next().unwrap())?; +// let default = if let Some(p) = pairs.next() { +// // TODO: check value is suitable for the type +// self.build_default_value(p)? +// } else { +// Value::Null +// }; +// Ok((Col { +// name, +// typ, +// default, +// }, is_key)) +// } +// +// fn build_col_defs(&self, pair: Pair) -> Result<(Vec, Vec)> { +// let mut keys = vec![]; +// let mut cols = vec![]; +// for pair in pair.into_inner() { +// let (col, is_key) = self.build_col_entry(pair)?; +// if is_key { +// keys.push(col) +// } else { +// cols.push(col) +// } +// } +// +// Ok((keys, cols)) +// } +// } +// +// #[repr(u8)] +// pub enum TableKind { +// Node = 1, +// Edge = 2, +// Columns = 3, +// Index = 4, +// } +// +// impl RocksStorage { +// #[allow(unused_variables)] +// fn all_metadata(&self) -> Result> { +// let default_cf = self.db.get_cf_handle("default")?; +// let it = self.db.iterator(&default_cf, None); +// let mut ret = vec![]; +// let env = self.root_env.write().expect("Root environment poisoned"); +// while it.is_valid() { +// let k = it.key(); +// let v = it.value(); +// let mut key_parser = ByteArrayParser::new(&k); +// let mut data_parser = ByteArrayParser::new(&v); +// key_parser.parse_varint().unwrap(); +// let table_name = key_parser.parse_value().unwrap().get_string().unwrap().to_string(); +// let table_kind = data_parser.parse_value().unwrap(); +// let table_id = TableId { name: table_name, local_id: 0 }; +// +// match table_kind { +// Value::UInt(i) if i == TableKind::Node as u64 => { +// let keys: Vec<_> = data_parser.parse_value().unwrap().get_list().unwrap() +// .iter().map(|v| { +// let vs = v.get_list().unwrap(); +// let mut vs = vs.iter(); +// let name = vs.next().unwrap().get_string().unwrap().to_string(); +// let typ = vs.next().unwrap().get_string().unwrap(); +// let typ = env.build_type_from_str(&typ).unwrap(); +// let default = vs.next().unwrap().owned_clone(); +// Col { +// name, +// typ, +// default, +// } +// }).collect(); +// let cols: Vec<_> = data_parser.parse_value().unwrap().get_list().unwrap() +// .iter().map(|v| { +// let vs = v.get_list().unwrap(); +// let mut vs = vs.iter(); +// let name = vs.next().unwrap().get_string().unwrap().to_string(); +// let typ = vs.next().unwrap().get_string().unwrap(); +// let typ = env.build_type_from_str(&typ).unwrap(); +// let default = vs.next().unwrap().owned_clone(); +// Col { +// name, +// typ, +// default, +// } +// }).collect(); +// let node = Node { +// status: StorageStatus::Stored, +// id: table_id, +// keys, +// cols, +// out_e: vec![], // TODO fix these +// in_e: vec![], +// attached: vec![], +// col_map: BTreeMap::new(), +// }; +// ret.push(Structured::Node(node)); +// } +// Value::UInt(i) if i == TableKind::Edge as u64 => { +// let src_name = data_parser.parse_value().unwrap().get_string().unwrap().to_string(); +// let dst_name = data_parser.parse_value().unwrap().get_string().unwrap().to_string(); +// let src_id = TableId { name: src_name, local_id: 0 }; +// let dst_id = TableId { name: dst_name, local_id: 0 }; +// let keys: Vec<_> = data_parser.parse_value().unwrap().get_list().unwrap() +// .iter().map(|v| { +// let vs = v.get_list().unwrap(); +// let mut vs = vs.iter(); +// let name = vs.next().unwrap().get_string().unwrap().to_string(); +// let typ = vs.next().unwrap().get_string().unwrap(); +// let typ = env.build_type_from_str(&typ).unwrap(); +// let default = vs.next().unwrap().owned_clone(); +// Col { +// name, +// typ, +// default, +// } +// }).collect(); +// let cols: Vec<_> = data_parser.parse_value().unwrap().get_list().unwrap() +// .iter().map(|v| { +// let vs = v.get_list().unwrap(); +// let mut vs = vs.iter(); +// let name = vs.next().unwrap().get_string().unwrap().to_string(); +// let typ = vs.next().unwrap().get_string().unwrap(); +// let typ = env.build_type_from_str(&typ).unwrap(); +// let default = vs.next().unwrap().owned_clone(); +// Col { +// name, +// typ, +// default, +// } +// }).collect(); +// let edge = Edge { +// status: StorageStatus::Stored, +// src: src_id, +// dst: dst_id, +// id: table_id, +// keys, +// cols, +// col_map: BTreeMap::new(), +// }; +// ret.push(Structured::Edge(edge)); +// } +// Value::UInt(i) if i == TableKind::Columns as u64 => { +// todo!() +// } +// Value::UInt(i) if i == TableKind::Index as u64 => { +// todo!() +// } +// _ => unreachable!() +// } +// +// it.next(); +// } +// Ok(ret) +// } +// +// fn persist_node(&mut self, node: &mut Node) -> Result<()> { +// // let mut key_writer = ByteArrayBuilder::with_capacity(8); +// // key_writer.build_varint(0); +// // key_writer.build_value(&Value::Text(Arc::new(Cow::from(&node.id.name)))); +// // let mut val_writer = ByteArrayBuilder::with_capacity(128); +// // val_writer.build_value(&Value::UInt(TableKind::Node as u64)); +// // val_writer.build_value(&Value::List(Arc::new(node.keys.iter().map(|k| { +// // Value::List(Arc::new(vec![ +// // Value::RefString(&k.name), +// // Value::OwnString(Arc::new(format!("{}", k.typ))), +// // k.default.clone(), +// // ])) +// // }).collect()))); +// // val_writer.build_value(&Value::List(Arc::new(node.cols.iter().map(|k| { +// // Value::List(Arc::new(vec![ +// // Value::RefString(&k.name), +// // Value::OwnString(Arc::new(format!("{}", k.typ))), +// // k.default.clone(), +// // ])) +// // }).collect()))); +// // +// // self.put_global(&key_writer.get(), &val_writer.get())?; +// // node.status = Stored; +// Ok(()) +// } +// +// fn persist_edge(&mut self, edge: &mut Edge) -> Result<()> { +// // let mut key_writer = ByteArrayBuilder::with_capacity(8); +// // key_writer.build_varint(0); +// // key_writer.build_value(&Value::RefString(&edge.id.name)); +// // +// // let mut val_writer = ByteArrayBuilder::with_capacity(128); +// // val_writer.build_value(&Value::UInt(TableKind::Edge as u64)); +// // val_writer.build_value(&Value::RefString(&edge.src.name)); +// // val_writer.build_value(&Value::RefString(&edge.dst.name)); +// // val_writer.build_value(&Value::List(Arc::new(edge.keys.iter().map(|k| { +// // Value::List(Arc::new(vec![ +// // Value::RefString(&k.name), +// // Value::OwnString(Arc::new(format!("{}", k.typ))), +// // k.default.clone(), +// // ])) +// // }).collect()))); +// // val_writer.build_value(&Value::List(Arc::new(edge.cols.iter().map(|k| { +// // Value::List(Arc::new(vec![ +// // Value::RefString(&k.name), +// // Value::OwnString(Arc::new(format!("{}", k.typ))), +// // k.default.clone(), +// // ])) +// // }).collect()))); +// // +// // self.put_global(&key_writer.get(), &val_writer.get())?; +// // edge.status = Stored; +// Ok(()) +// } +// } +// +// impl Evaluator { +// pub fn restore_metadata(&mut self) -> Result<()> { +// let mds = self.storage.all_metadata()?; +// for md in &mds { +// match md { +// v @ Structured::Node(n) => { +// // TODO: check if they are the same if one already exists +// self.root_define(n.id.name.clone(), v.clone()); +// } +// v @ Structured::Edge(e) => { +// self.root_define(e.id.name.clone(), v.clone()); +// } +// Structured::Columns(_) => {} +// Structured::Index(_) => {} +// Structured::Typing(_) => unreachable!(), +// Structured::Value(_) => unreachable!() +// } +// } +// Ok(()) +// } +// +// // fn persist_change(&mut self, tname: &str, global: bool) -> Result<()> { +// // self.storage.create_table(tname, global)?; +// // let tbl = { +// // self.resolve_mut(tname).unwrap() +// // }; +// // if global { +// // match tbl { +// // Structured::Node(n) => self.storage.persist_node(n), +// // Structured::Edge(e) => self.storage.persist_edge(e), +// // Structured::Columns(_) => unimplemented!(), +// // Structured::Index(_) => unimplemented!(), +// // Structured::Typing(_) => panic!(), +// // Structured::Value(_) => unreachable!() +// // } +// // } else { +// // Ok(()) +// // } +// // } +// +// +// pub fn build_table(&mut self, pairs: Pairs) -> Result<()> { +// let mut new_tables = vec![]; +// for pair in pairs { +// match pair.as_rule() { +// r @ (Rule::global_def | Rule::local_def) => { +// let inner = pair.into_inner().next().unwrap(); +// let global = r == Rule::global_def; +// let local_id = self.storage.get_next_local_id(global); +// let mut env_to_build = +// // if global { +// // self.storage.root_env.write().expect("Root environment poisoned").borrow_mut() +// // } else { +// self.env_stack.last_mut().unwrap() +// ; +// // }; +// new_tables.push((global, match inner.as_rule() { +// Rule::node_def => { +// env_to_build.build_node_def(inner, local_id)? +// } +// Rule::edge_def => { +// env_to_build.build_edge_def(inner, local_id)? +// } +// Rule::columns_def => { +// env_to_build.build_columns_def(inner, local_id)? +// } +// Rule::index_def => { +// env_to_build.build_index_def(inner, local_id)? +// } +// _ => todo!() +// })); +// } +// Rule::EOI => {} +// _ => unreachable!() +// } +// } +// for (global, tname) in &new_tables { +// // self.persist_change(tname, *global).unwrap(); // TODO proper error handling +// } +// Ok(()) +// } +// +// pub fn insert_data(&mut self, _pairs: Pairs, _bindings: BTreeMap<&str, Value>) -> Result<()> { +// todo!() +// } +// } +// +// +// #[cfg(test)] +// mod tests { +// use super::*; +// use pest::Parser as PestParser; +// use crate::eval::EvaluatorWithStorage; +// use crate::parser::Parser; +// +// fn send_sync(_x: &X) {} +// +// #[test] +// fn definitions() { +// let s = r#" +// create node "Person" { +// *id: Int, +// name: String, +// email: ?String, +// habits: ?[?String] +// } +// +// create edge (Person)-[Friend]->(Person) { +// relation: ?String +// } +// "#; +// let parsed = Parser::parse(Rule::file, s).unwrap(); +// let db = RocksStorage::new("_path_for_rocksdb_storagex".to_string()).unwrap(); +// send_sync(&db); +// let mut eval = EvaluatorWithStorage::new(db).unwrap(); +// eval.build_table(parsed).unwrap(); +// eval.restore_metadata().unwrap(); +// // eval.storage.delete_storage().unwrap(); +// println!("{:#?}", eval.resolve("Person")); +// println!("{:#?}", eval.resolve("Friend")); +// } +// } \ No newline at end of file diff --git a/src/env.rs b/src/env.rs index 7631fd89..3bf25153 100644 --- a/src/env.rs +++ b/src/env.rs @@ -1,61 +1,61 @@ -use std::borrow::Cow; -use std::collections::BTreeMap; -use crate::typing::{Structured}; - -pub trait Env where V: Clone { - fn define(&mut self, name: String, value: V) -> Option; - fn define_new(&mut self, name: String, value: V) -> bool; - fn resolve(&self, name: &str) -> Option>; - fn resolve_mut(&mut self, name: &str) -> Option<&mut V>; - fn undef(&mut self, name: &str) -> Option; -} - -pub trait LayeredEnv: Env where V: Clone { - fn root_define(&mut self, name: String, value: V) -> Option; - fn root_define_new(&mut self, name: String, value: V) -> bool; - fn root_resolve(&self, name: &str) -> Option>; - fn root_undef(&mut self, name: &str) -> Option; -} - - -pub struct Environment { - map: BTreeMap, -} - - -impl Default for Environment { - fn default() -> Self { - Self { map: BTreeMap::new() } - } -} - -impl Env for Environment { - fn define(&mut self, name: String, value: Structured) -> Option { - let old = self.map.remove(&name); - self.map.insert(name, value); - old - } - - fn define_new(&mut self, name: String, value: Structured) -> bool { - if let std::collections::btree_map::Entry::Vacant(e) = self.map.entry(name) { - e.insert(value); - true - } else { - false - } - } - - fn resolve(&self, name: &str) -> Option> { - self.map.get(name) - .map(|v| Cow::Borrowed(v)) - } - - fn resolve_mut(&mut self, name: &str) -> Option<&mut Structured> { - self.map.get_mut(name) - } - - - fn undef(&mut self, name: &str) -> Option { - self.map.remove(name) - } -} +// use std::borrow::Cow; +// use std::collections::BTreeMap; +// use crate::typing::{Structured}; +// +// pub trait Env where V: Clone { +// fn define(&mut self, name: String, value: V) -> Option; +// fn define_new(&mut self, name: String, value: V) -> bool; +// fn resolve(&self, name: &str) -> Option>; +// fn resolve_mut(&mut self, name: &str) -> Option<&mut V>; +// fn undef(&mut self, name: &str) -> Option; +// } +// +// pub trait LayeredEnv: Env where V: Clone { +// fn root_define(&mut self, name: String, value: V) -> Option; +// fn root_define_new(&mut self, name: String, value: V) -> bool; +// fn root_resolve(&self, name: &str) -> Option>; +// fn root_undef(&mut self, name: &str) -> Option; +// } +// +// +// pub struct Environment { +// map: BTreeMap, +// } +// +// +// impl Default for Environment { +// fn default() -> Self { +// Self { map: BTreeMap::new() } +// } +// } +// +// impl Env for Environment { +// fn define(&mut self, name: String, value: Structured) -> Option { +// let old = self.map.remove(&name); +// self.map.insert(name, value); +// old +// } +// +// fn define_new(&mut self, name: String, value: Structured) -> bool { +// if let std::collections::btree_map::Entry::Vacant(e) = self.map.entry(name) { +// e.insert(value); +// true +// } else { +// false +// } +// } +// +// fn resolve(&self, name: &str) -> Option> { +// self.map.get(name) +// .map(|v| Cow::Borrowed(v)) +// } +// +// fn resolve_mut(&mut self, name: &str) -> Option<&mut Structured> { +// self.map.get_mut(name) +// } +// +// +// fn undef(&mut self, name: &str) -> Option { +// self.map.remove(name) +// } +// } diff --git a/src/error.rs b/src/error.rs index 8db7e603..3ed3f38a 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,65 +1,65 @@ -use std::result; -use thiserror::Error; -use crate::parser::Rule; - -#[derive(Error, Debug)] -pub enum CozoError { - #[error("Invalid UTF code")] - InvalidUtfCode, - - #[error("Invalid escape sequence")] - InvalidEscapeSequence, - - #[error("Type mismatch")] - TypeError, - - #[error("Reserved identifier")] - ReservedIdent, - - #[error("The requested name exists")] - NameConflict, - - #[error("Undefined type")] - UndefinedType, - - #[error("Undefined table")] - UndefinedTable, - - #[error("Undefined parameter")] - UndefinedParam, - - #[error("Value required")] - ValueRequired, - - #[error("Incompatible value")] - IncompatibleValue, - - #[error("Wrong type")] - WrongType, - - #[error("Cannot have global edge between local nodes")] - IncompatibleEdge, - - #[error("Unexpected index columns found")] - UnexpectedIndexColumns, - - #[error("Database already closed")] - DatabaseClosed, - - #[error(transparent)] - ParseInt(#[from] std::num::ParseIntError), - - #[error(transparent)] - ParseFloat(#[from] std::num::ParseFloatError), - - #[error(transparent)] - Parse(#[from] pest::error::Error), - - #[error(transparent)] - Storage(#[from] cozo_rocks::BridgeStatus), - - #[error(transparent)] - Io(#[from] std::io::Error), -} - -pub type Result = result::Result; \ No newline at end of file +// use std::result; +// use thiserror::Error; +// use crate::parser::Rule; +// +// #[derive(Error, Debug)] +// pub enum CozoError { +// #[error("Invalid UTF code")] +// InvalidUtfCode, +// +// #[error("Invalid escape sequence")] +// InvalidEscapeSequence, +// +// #[error("Type mismatch")] +// TypeError, +// +// #[error("Reserved identifier")] +// ReservedIdent, +// +// #[error("The requested name exists")] +// NameConflict, +// +// #[error("Undefined type")] +// UndefinedType, +// +// #[error("Undefined table")] +// UndefinedTable, +// +// #[error("Undefined parameter")] +// UndefinedParam, +// +// #[error("Value required")] +// ValueRequired, +// +// #[error("Incompatible value")] +// IncompatibleValue, +// +// #[error("Wrong type")] +// WrongType, +// +// #[error("Cannot have global edge between local nodes")] +// IncompatibleEdge, +// +// #[error("Unexpected index columns found")] +// UnexpectedIndexColumns, +// +// #[error("Database already closed")] +// DatabaseClosed, +// +// #[error(transparent)] +// ParseInt(#[from] std::num::ParseIntError), +// +// #[error(transparent)] +// ParseFloat(#[from] std::num::ParseFloatError), +// +// #[error(transparent)] +// Parse(#[from] pest::error::Error), +// +// #[error(transparent)] +// Storage(#[from] cozo_rocks::BridgeStatus), +// +// #[error(transparent)] +// Io(#[from] std::io::Error), +// } +// +// pub type Result = result::Result; \ No newline at end of file diff --git a/src/eval.rs b/src/eval.rs index 3a743be7..e9c784d6 100644 --- a/src/eval.rs +++ b/src/eval.rs @@ -1,622 +1,620 @@ -use std::borrow::{Borrow, Cow}; -use std::sync::Arc; -use crate::ast::Expr; -use crate::ast::Expr::*; -use crate::error::Result; -use crate::error::CozoError; -use crate::error::CozoError::*; -use crate::value::Value::*; -use crate::ast::*; -use crate::env::{Env, Environment, LayeredEnv}; -use crate::storage::{DummyStorage, RocksStorage, Storage}; -use crate::typing::Structured; - -pub struct Evaluator { - pub env_stack: Vec, - pub storage: S, -} - -impl Env for Evaluator { - fn define(&mut self, name: String, value: Structured) -> Option { - None - } - - fn define_new(&mut self, name: String, value: Structured) -> bool { - false - } - - fn resolve(&self, name: &str) -> Option> { - None - } - - fn resolve_mut(&mut self, name: &str) -> Option<&mut Structured> { - None - } - - fn undef(&mut self, name: &str) -> Option { - None - } -} - -impl Env for Evaluator { - fn define(&mut self, name: String, value: Structured) -> Option { - self.env_stack.last_mut().unwrap().define(name, value) - } - - fn define_new(&mut self, name: String, value: Structured) -> bool { - if self.env_stack.is_empty() { - self.env_stack.push(Environment::default()); - } - self.env_stack.last_mut().unwrap().define_new(name, value) - } - - fn resolve(&self, name: &str) -> Option> { - let mut res = None; - for item in self.env_stack.iter().rev() { - res = item.resolve(name); - if res.is_some() { - return res; - } - } - // Unwrap here because read() only fails if lock is poisoned - let env = self.storage.root_env.read().expect("Root environment is poisoned"); - env.resolve(name).map(|v| Cow::Owned(v.into_owned())) - } - - fn resolve_mut(&mut self, name: &str) -> Option<&mut Structured> { - // Cannot obtain root elements this way - let mut res = None; - for item in self.env_stack.iter_mut().rev() { - res = item.resolve_mut(name); - if res.is_some() { - return res; - } - } - res - } - - fn undef(&mut self, name: &str) -> Option { - // Cannot undef root elements this way - let mut res = None; - for item in self.env_stack.iter_mut().rev() { - res = item.undef(name); - if res.is_some() { - return res; - } - } - res - } -} - -impl LayeredEnv for Evaluator { - fn root_define(&mut self, name: String, value: Structured) -> Option { - self.storage.root_env.write().expect("Root environment is poisoned") - .define(name, value) - } - - fn root_define_new(&mut self, name: String, value: Structured) -> bool { - self.storage.root_env.write().expect("Root environment is poisoned") - .define_new(name, value) - } - - fn root_resolve(&self, name: &str) -> Option> { - let env = self.storage.root_env.read().expect("Root environment is poisoned"); - env.resolve(name).map(|v| Cow::Owned(v.into_owned())) - } - - fn root_undef(&mut self, name: &str) -> Option { - self.storage.root_env.write().expect("Root environment is poisoned") - .undef(name) - } -} - -pub type EvaluatorWithStorage = Evaluator; -pub type BareEvaluator = Evaluator; - -impl Evaluator { - pub fn new(storage: S) -> Result { - Ok(Self { - env_stack: vec![Environment::default()], - storage, - }) - } -} - - -impl<'a, S: Storage> ExprVisitor<'a, Result>> for Evaluator - where Evaluator: Env { - fn visit_expr(&self, ex: &Expr<'a>) -> Result> { - match ex { - Apply(op, args) => { - match op { - Op::Add => self.add_exprs(args), - Op::Sub => self.sub_exprs(args), - Op::Mul => self.mul_exprs(args), - Op::Div => self.div_exprs(args), - Op::Eq => self.eq_exprs(args), - Op::Neq => self.ne_exprs(args), - Op::Gt => self.gt_exprs(args), - Op::Lt => self.lt_exprs(args), - Op::Ge => self.ge_exprs(args), - Op::Le => self.le_exprs(args), - Op::Neg => self.negate_expr(args), - Op::Minus => self.minus_expr(args), - Op::Mod => self.mod_exprs(args), - Op::Or => self.or_expr(args), - Op::And => self.and_expr(args), - Op::Coalesce => self.coalesce_exprs(args), - Op::Pow => self.pow_exprs(args), - Op::IsNull => self.test_null_expr(args), - Op::NotNull => self.not_null_expr(args), - Op::Call => unimplemented!(), - } - } - Const(v) => Ok(Const(v.clone())), - Expr::List(_) => { unimplemented!() } - Expr::Dict(_, _) => { unimplemented!() } - Ident(ident) => { - let resolved = self.resolve(ident).ok_or(UndefinedParam)?; - match resolved.borrow() { - Structured::Value(v) => { - Ok(Const(v.clone())) - } - _ => return Err(ValueRequired) - } - } - } - } -} - -impl Evaluator - where Evaluator: Env { - fn add_exprs<'a>(&self, exprs: &[Expr<'a>]) -> Result> { - match exprs { - [a, b] => { - let a = self.visit_expr(a)?; - let b = self.visit_expr(b)?; - if a == Const(Null) || b == Const(Null) { - return Ok(Const(Null)); - } - Ok(Const(match (a, b) { - (Const(a), Const(b)) => { - match (a, b) { - (Int(va), Int(vb)) => Int(va + vb), - (Float(va), Int(vb)) => Float(va + vb as f64), - (Int(va), Float(vb)) => Float(va as f64 + vb), - (Float(va), Float(vb)) => Float(va + vb), - (OwnString(va), OwnString(vb)) => OwnString(Arc::new(va.clone().to_string() + &vb)), - (OwnString(va), RefString(vb)) => OwnString(Arc::new(va.clone().to_string() + &*vb)), - (RefString(va), OwnString(vb)) => OwnString(Arc::new(va.to_string() + &*vb)), - (RefString(va), RefString(vb)) => OwnString(Arc::new(va.to_string() + &*vb)), - (_, _) => return Err(CozoError::TypeError) - } - } - (a, b) => return Ok(Apply(Op::Add, vec![a, b])) - })) - } - _ => unreachable!() - } - } - - fn sub_exprs<'a>(&self, exprs: &[Expr<'a>]) -> Result> { - match exprs { - [a, b] => { - let a = self.visit_expr(a)?; - let b = self.visit_expr(b)?; - if a == Const(Null) || b == Const(Null) { - return Ok(Const(Null)); - } - Ok(Const(match (a, b) { - (Const(a), Const(b)) => { - match (a, b) { - (Int(va), Int(vb)) => Int(va - vb), - (Float(va), Int(vb)) => Float(va - vb as f64), - (Int(va), Float(vb)) => Float(va as f64 - vb), - (Float(va), Float(vb)) => Float(va - vb), - (_, _) => return Err(CozoError::TypeError) - } - } - (a, b) => return Ok(Apply(Op::Sub, vec![a, b])) - })) - } - _ => unreachable!() - } - } - - fn mul_exprs<'a>(&self, exprs: &[Expr<'a>]) -> Result> { - match exprs { - [a, b] => { - let a = self.visit_expr(a)?; - let b = self.visit_expr(b)?; - if a == Const(Null) || b == Const(Null) { - return Ok(Const(Null)); - } - Ok(Const(match (a, b) { - (Const(a), Const(b)) => { - match (a, b) { - (Int(va), Int(vb)) => Int(va * vb), - (Float(va), Int(vb)) => Float(va * vb as f64), - (Int(va), Float(vb)) => Float(va as f64 * vb), - (Float(va), Float(vb)) => Float(va * vb), - (_, _) => return Err(CozoError::TypeError) - } - } - (a, b) => return Ok(Apply(Op::Mul, vec![a, b])) - })) - } - _ => unreachable!() - } - } - - fn div_exprs<'a>(&self, exprs: &[Expr<'a>]) -> Result> { - match exprs { - [a, b] => { - let a = self.visit_expr(a)?; - let b = self.visit_expr(b)?; - if a == Const(Null) || b == Const(Null) { - return Ok(Const(Null)); - } - Ok(Const(match (a, b) { - (Const(a), Const(b)) => { - match (a, b) { - (Int(va), Int(vb)) => Float(va as f64 / vb as f64), - (Float(va), Int(vb)) => Float(va / vb as f64), - (Int(va), Float(vb)) => Float(va as f64 / vb), - (Float(va), Float(vb)) => Float(va / vb), - (_, _) => return Err(CozoError::TypeError) - } - } - (a, b) => return Ok(Apply(Op::Div, vec![a, b])) - })) - } - _ => unreachable!() - } - } - - fn mod_exprs<'a>(&self, exprs: &[Expr<'a>]) -> Result> { - match exprs { - [a, b] => { - let a = self.visit_expr(a)?; - let b = self.visit_expr(b)?; - if a == Const(Null) || b == Const(Null) { - return Ok(Const(Null)); - } - Ok(Const(match (a, b) { - (Const(a), Const(b)) => { - match (a, b) { - (Int(a), Int(b)) => Int(a % b), - (_, _) => return Err(CozoError::TypeError) - } - } - (a, b) => return Ok(Apply(Op::Mod, vec![a, b])) - })) - } - _ => unreachable!() - } - } - - fn eq_exprs<'a>(&self, exprs: &[Expr<'a>]) -> Result> { - match exprs { - [a, b] => { - let a = self.visit_expr(a)?; - let b = self.visit_expr(b)?; - if a == Const(Null) || b == Const(Null) { - return Ok(Const(Null)); - } - match (a, b) { - (Const(a), Const(b)) => Ok(Const(Bool(a == b))), - (a, b) => Ok(Apply(Op::Eq, vec![a, b])) - } - } - _ => unreachable!() - } - } - - fn ne_exprs<'a>(&self, exprs: &[Expr<'a>]) -> Result> { - match exprs { - [a, b] => { - let a = self.visit_expr(a)?; - let b = self.visit_expr(b)?; - if a == Const(Null) || b == Const(Null) { - return Ok(Const(Null)); - } - match (a, b) { - (Const(a), Const(b)) => Ok(Const(Bool(a != b))), - (a, b) => Ok(Apply(Op::Neq, vec![a, b])) - } - } - _ => unreachable!() - } - } - - fn gt_exprs<'a>(&self, exprs: &[Expr<'a>]) -> Result> { - match exprs { - [a, b] => { - let a = self.visit_expr(a)?; - let b = self.visit_expr(b)?; - if a == Const(Null) || b == Const(Null) { - return Ok(Const(Null)); - } - match (a, b) { - (Const(a), Const(b)) => { - match (a, b) { - (Int(a), Int(b)) => Ok(Const(Bool(a > b))), - (Float(a), Int(b)) => Ok(Const(Bool(a > b as f64))), - (Int(a), Float(b)) => Ok(Const(Bool(a as f64 > b))), - (Float(a), Float(b)) => Ok(Const(Bool(a > b))), - (_, _) => Err(CozoError::TypeError) - } - } - (a, b) => Ok(Apply(Op::Gt, vec![a, b])) - } - } - _ => unreachable!() - } - } - - fn ge_exprs<'a>(&self, exprs: &[Expr<'a>]) -> Result> { - match exprs { - [a, b] => { - let a = self.visit_expr(a)?; - let b = self.visit_expr(b)?; - if a == Const(Null) || b == Const(Null) { - return Ok(Const(Null)); - } - match (a, b) { - (Const(a), Const(b)) => { - match (a, b) { - (Int(a), Int(b)) => Ok(Const(Bool(a >= b))), - (Float(a), Int(b)) => Ok(Const(Bool(a >= b as f64))), - (Int(a), Float(b)) => Ok(Const(Bool(a as f64 >= b))), - (Float(a), Float(b)) => Ok(Const(Bool(a >= b))), - (_, _) => Err(CozoError::TypeError) - } - } - (a, b) => Ok(Apply(Op::Ge, vec![a, b])) - } - } - _ => unreachable!() - } - } - - fn lt_exprs<'a>(&self, exprs: &[Expr<'a>]) -> Result> { - match exprs { - [a, b] => { - let a = self.visit_expr(a)?; - let b = self.visit_expr(b)?; - if a == Const(Null) || b == Const(Null) { - return Ok(Const(Null)); - } - match (a, b) { - (Const(a), Const(b)) => { - match (a, b) { - (Int(a), Int(b)) => Ok(Const(Bool(a < b))), - (Float(a), Int(b)) => Ok(Const(Bool(a < b as f64))), - (Int(a), Float(b)) => Ok(Const(Bool((a as f64) < b))), - (Float(a), Float(b)) => Ok(Const(Bool(a < b))), - (_, _) => Err(CozoError::TypeError) - } - } - (a, b) => Ok(Apply(Op::Lt, vec![a, b])) - } - } - _ => unreachable!() - } - } - - fn le_exprs<'a>(&self, exprs: &[Expr<'a>]) -> Result> { - match exprs { - [a, b] => { - let a = self.visit_expr(a)?; - let b = self.visit_expr(b)?; - if a == Const(Null) || b == Const(Null) { - return Ok(Const(Null)); - } - match (a, b) { - (Const(a), Const(b)) => { - match (a, b) { - (Int(a), Int(b)) => Ok(Const(Bool(a <= b))), - (Float(a), Int(b)) => Ok(Const(Bool(a <= b as f64))), - (Int(a), Float(b)) => Ok(Const(Bool((a as f64) <= b))), - (Float(a), Float(b)) => Ok(Const(Bool(a <= b))), - (_, _) => Err(CozoError::TypeError) - } - } - (a, b) => Ok(Apply(Op::Le, vec![a, b])) - } - } - _ => unreachable!() - } - } - - fn pow_exprs<'a>(&self, exprs: &[Expr<'a>]) -> Result> { - match exprs { - [a, b] => { - let a = self.visit_expr(a)?; - let b = self.visit_expr(b)?; - if a == Const(Null) || b == Const(Null) { - return Ok(Const(Null)); - } - match (a, b) { - (Const(a), Const(b)) => { - match (a, b) { - (Int(a), Int(b)) => Ok(Const(Float((a as f64).powf(b as f64)))), - (Float(a), Int(b)) => Ok(Const(Float(a.powi(b as i32)))), - (Int(a), Float(b)) => Ok(Const(Float((a as f64).powf(b)))), - (Float(a), Float(b)) => Ok(Const(Float(a.powf(b)))), - (_, _) => Err(CozoError::TypeError) - } - } - (a, b) => Ok(Apply(Op::Pow, vec![a, b])) - } - } - _ => unreachable!() - } - } - - fn coalesce_exprs<'a>(&self, exprs: &[Expr<'a>]) -> Result> { - match exprs { - [a, b] => { - let a = self.visit_expr(a)?; - let b = self.visit_expr(b)?; - if a == Const(Null) { - return Ok(b); - } - if b == Const(Null) { - return Ok(a); - } - if let a @ Const(_) = a { - return Ok(a); - } - return Ok(Apply(Op::Coalesce, vec![a, b])); - } - _ => unreachable!() - } - } - - fn negate_expr<'a>(&self, exprs: &[Expr<'a>]) -> Result> { - Ok(match exprs { - [a] => { - match self.visit_expr(a)? { - Const(Null) => Const(Null), - Const(Bool(b)) => Const(Bool(!b)), - Const(_) => return Err(TypeError), - Apply(Op::Neg, v) => v.into_iter().next().unwrap(), - Apply(Op::IsNull, v) => Apply(Op::NotNull, v), - Apply(Op::NotNull, v) => Apply(Op::IsNull, v), - Apply(Op::Eq, v) => Apply(Op::Neq, v), - Apply(Op::Neq, v) => Apply(Op::Eq, v), - Apply(Op::Gt, v) => Apply(Op::Le, v), - Apply(Op::Ge, v) => Apply(Op::Lt, v), - Apply(Op::Le, v) => Apply(Op::Gt, v), - Apply(Op::Lt, v) => Apply(Op::Ge, v), - v => Apply(Op::Neg, vec![v]) - } - } - _ => unreachable!() - }) - } - - fn minus_expr<'a>(&self, exprs: &[Expr<'a>]) -> Result> { - Ok(match exprs { - [a] => { - match self.visit_expr(a)? { - Const(Null) => Const(Null), - Const(Int(i)) => Const(Int(-i)), - Const(Float(f)) => Const(Float(-f)), - Const(_) => return Err(TypeError), - Apply(Op::Minus, v) => v.into_iter().next().unwrap(), - v => Apply(Op::Minus, vec![v]) - } - } - _ => unreachable!() - }) - } - - fn test_null_expr<'a>(&self, exprs: &[Expr<'a>]) -> Result> { - Ok(match exprs { - [a] => { - match self.visit_expr(a)? { - Const(Null) => Const(Bool(true)), - Const(_) => Const(Bool(false)), - v => Apply(Op::IsNull, vec![v]) - } - } - _ => unreachable!() - }) - } - - fn not_null_expr<'a>(&self, exprs: &[Expr<'a>]) -> Result> { - Ok(match exprs { - [a] => { - match self.visit_expr(a)? { - Const(Null) => Const(Bool(false)), - Const(_) => Const(Bool(true)), - v => Apply(Op::IsNull, vec![v]) - } - } - _ => unreachable!() - }) - } - - fn or_expr<'a>(&self, exprs: &[Expr<'a>]) -> Result> { - let mut unevaluated = vec![]; - let mut has_null = false; - for expr in exprs { - match self.visit_expr(expr)? { - Const(Bool(true)) => return Ok(Const(Bool(true))), - Const(Bool(false)) => {} - Const(Null) => { has_null = true } - Const(_) => return Err(TypeError), - Apply(Op::Or, vs) => { - for el in vs { - match el { - Const(Null) => has_null = true, - Const(_) => unreachable!(), - v => unevaluated.push(v) - } - } - } - v => unevaluated.push(v) - } - } - match (has_null, unevaluated.len()) { - (true, 0) => Ok(Const(Null)), - (false, 0) => Ok(Const(Bool(false))), - (false, _) => Ok(Apply(Op::Or, unevaluated)), - (true, _) => { - unevaluated.push(Const(Null)); - Ok(Apply(Op::Or, unevaluated)) - } - } - } - - fn and_expr<'a>(&self, exprs: &[Expr<'a>]) -> Result> { - let mut unevaluated = vec![]; - let mut no_null = true; - for expr in exprs { - match self.visit_expr(expr)? { - Const(Bool(false)) => return Ok(Const(Bool(false))), - Const(Bool(true)) => {} - Const(Null) => no_null = false, - Const(_) => return Err(TypeError), - Apply(Op::Or, vs) => { - for el in vs { - match el { - Const(Null) => no_null = false, - Const(_) => unreachable!(), - v => unevaluated.push(v) - } - } - } - v => unevaluated.push(v) - } - } - match (no_null, unevaluated.len()) { - (true, 0) => Ok(Const(Bool(true))), - (false, 0) => Ok(Const(Null)), - (true, _) => Ok(Apply(Op::Add, unevaluated)), - (false, _) => { - unevaluated.push(Const(Null)); - Ok(Apply(Op::And, unevaluated)) - } - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn operators() { - let ev = Evaluator::new(DummyStorage {}).unwrap(); - - println!("{:#?}", ev.visit_expr(&parse_expr_from_str("1/10+(-2+3)*4^5").unwrap()).unwrap()); - println!("{:#?}", ev.visit_expr(&parse_expr_from_str("true && false").unwrap()).unwrap()); - println!("{:#?}", ev.visit_expr(&parse_expr_from_str("true || false").unwrap()).unwrap()); - println!("{:#?}", ev.visit_expr(&parse_expr_from_str("true || null").unwrap()).unwrap()); - println!("{:#?}", ev.visit_expr(&parse_expr_from_str("null || true").unwrap()).unwrap()); - println!("{:#?}", ev.visit_expr(&parse_expr_from_str("true && null").unwrap()).unwrap()); - } -} \ No newline at end of file +// use std::borrow::{Borrow, Cow}; +// use std::sync::Arc; +// use crate::ast::Expr; +// use crate::ast::Expr::*; +// use crate::error::Result; +// use crate::error::CozoError; +// use crate::error::CozoError::*; +// use crate::value::Value::*; +// use crate::ast::*; +// use crate::env::{Env, Environment, LayeredEnv}; +// use crate::storage::{DummyStorage, RocksStorage, Storage}; +// use crate::typing::Structured; +// +// pub struct Evaluator { +// pub env_stack: Vec, +// pub storage: S, +// } +// +// impl Env for Evaluator { +// fn define(&mut self, name: String, value: Structured) -> Option { +// None +// } +// +// fn define_new(&mut self, name: String, value: Structured) -> bool { +// false +// } +// +// fn resolve(&self, name: &str) -> Option> { +// None +// } +// +// fn resolve_mut(&mut self, name: &str) -> Option<&mut Structured> { +// None +// } +// +// fn undef(&mut self, name: &str) -> Option { +// None +// } +// } +// +// impl Env for Evaluator { +// fn define(&mut self, name: String, value: Structured) -> Option { +// self.env_stack.last_mut().unwrap().define(name, value) +// } +// +// fn define_new(&mut self, name: String, value: Structured) -> bool { +// if self.env_stack.is_empty() { +// self.env_stack.push(Environment::default()); +// } +// self.env_stack.last_mut().unwrap().define_new(name, value) +// } +// +// fn resolve(&self, name: &str) -> Option> { +// let mut res = None; +// for item in self.env_stack.iter().rev() { +// res = item.resolve(name); +// if res.is_some() { +// return res; +// } +// } +// // Unwrap here because read() only fails if lock is poisoned +// let env = self.storage.root_env.read().expect("Root environment is poisoned"); +// env.resolve(name).map(|v| Cow::Owned(v.into_owned())) +// } +// +// fn resolve_mut(&mut self, name: &str) -> Option<&mut Structured> { +// // Cannot obtain root elements this way +// let mut res = None; +// for item in self.env_stack.iter_mut().rev() { +// res = item.resolve_mut(name); +// if res.is_some() { +// return res; +// } +// } +// res +// } +// +// fn undef(&mut self, name: &str) -> Option { +// // Cannot undef root elements this way +// let mut res = None; +// for item in self.env_stack.iter_mut().rev() { +// res = item.undef(name); +// if res.is_some() { +// return res; +// } +// } +// res +// } +// } +// +// impl LayeredEnv for Evaluator { +// fn root_define(&mut self, name: String, value: Structured) -> Option { +// self.storage.root_env.write().expect("Root environment is poisoned") +// .define(name, value) +// } +// +// fn root_define_new(&mut self, name: String, value: Structured) -> bool { +// self.storage.root_env.write().expect("Root environment is poisoned") +// .define_new(name, value) +// } +// +// fn root_resolve(&self, name: &str) -> Option> { +// let env = self.storage.root_env.read().expect("Root environment is poisoned"); +// env.resolve(name).map(|v| Cow::Owned(v.into_owned())) +// } +// +// fn root_undef(&mut self, name: &str) -> Option { +// self.storage.root_env.write().expect("Root environment is poisoned") +// .undef(name) +// } +// } +// +// pub type EvaluatorWithStorage = Evaluator; +// pub type BareEvaluator = Evaluator; +// +// impl Evaluator { +// pub fn new(storage: S) -> Result { +// Ok(Self { +// env_stack: vec![Environment::default()], +// storage, +// }) +// } +// } +// +// +// impl<'a, S: Storage> ExprVisitor<'a, Result>> for Evaluator +// where Evaluator: Env { +// fn visit_expr(&self, ex: &Expr<'a>) -> Result> { +// match ex { +// Apply(op, args) => { +// match op { +// Op::Add => self.add_exprs(args), +// Op::Sub => self.sub_exprs(args), +// Op::Mul => self.mul_exprs(args), +// Op::Div => self.div_exprs(args), +// Op::Eq => self.eq_exprs(args), +// Op::Neq => self.ne_exprs(args), +// Op::Gt => self.gt_exprs(args), +// Op::Lt => self.lt_exprs(args), +// Op::Ge => self.ge_exprs(args), +// Op::Le => self.le_exprs(args), +// Op::Neg => self.negate_expr(args), +// Op::Minus => self.minus_expr(args), +// Op::Mod => self.mod_exprs(args), +// Op::Or => self.or_expr(args), +// Op::And => self.and_expr(args), +// Op::Coalesce => self.coalesce_exprs(args), +// Op::Pow => self.pow_exprs(args), +// Op::IsNull => self.test_null_expr(args), +// Op::NotNull => self.not_null_expr(args), +// Op::Call => unimplemented!(), +// } +// } +// Const(v) => Ok(Const(v.clone())), +// Expr::List(_) => { unimplemented!() } +// Expr::Dict(_, _) => { unimplemented!() } +// Ident(ident) => { +// let resolved = self.resolve(ident).ok_or(UndefinedParam)?; +// match resolved.borrow() { +// Structured::Value(v) => { +// Ok(Const(v.clone())) +// } +// _ => return Err(ValueRequired) +// } +// } +// } +// } +// } +// +// impl Evaluator +// where Evaluator: Env { +// fn add_exprs<'a>(&self, exprs: &[Expr<'a>]) -> Result> { +// match exprs { +// [a, b] => { +// let a = self.visit_expr(a)?; +// let b = self.visit_expr(b)?; +// if a == Const(Null) || b == Const(Null) { +// return Ok(Const(Null)); +// } +// Ok(Const(match (a, b) { +// (Const(a), Const(b)) => { +// match (a, b) { +// (Int(va), Int(vb)) => Int(va + vb), +// (Float(va), Int(vb)) => Float(va + vb as f64), +// (Int(va), Float(vb)) => Float(va as f64 + vb), +// (Float(va), Float(vb)) => Float(va + vb), +// (Text(va), Text(vb)) => +// Text(Arc::new(Cow::Owned(va.clone().to_string() + &vb))), +// (_, _) => return Err(CozoError::TypeError) +// } +// } +// (a, b) => return Ok(Apply(Op::Add, vec![a, b])) +// })) +// } +// _ => unreachable!() +// } +// } +// +// fn sub_exprs<'a>(&self, exprs: &[Expr<'a>]) -> Result> { +// match exprs { +// [a, b] => { +// let a = self.visit_expr(a)?; +// let b = self.visit_expr(b)?; +// if a == Const(Null) || b == Const(Null) { +// return Ok(Const(Null)); +// } +// Ok(Const(match (a, b) { +// (Const(a), Const(b)) => { +// match (a, b) { +// (Int(va), Int(vb)) => Int(va - vb), +// (Float(va), Int(vb)) => Float(va - vb as f64), +// (Int(va), Float(vb)) => Float(va as f64 - vb), +// (Float(va), Float(vb)) => Float(va - vb), +// (_, _) => return Err(CozoError::TypeError) +// } +// } +// (a, b) => return Ok(Apply(Op::Sub, vec![a, b])) +// })) +// } +// _ => unreachable!() +// } +// } +// +// fn mul_exprs<'a>(&self, exprs: &[Expr<'a>]) -> Result> { +// match exprs { +// [a, b] => { +// let a = self.visit_expr(a)?; +// let b = self.visit_expr(b)?; +// if a == Const(Null) || b == Const(Null) { +// return Ok(Const(Null)); +// } +// Ok(Const(match (a, b) { +// (Const(a), Const(b)) => { +// match (a, b) { +// (Int(va), Int(vb)) => Int(va * vb), +// (Float(va), Int(vb)) => Float(va * vb as f64), +// (Int(va), Float(vb)) => Float(va as f64 * vb), +// (Float(va), Float(vb)) => Float(va * vb), +// (_, _) => return Err(CozoError::TypeError) +// } +// } +// (a, b) => return Ok(Apply(Op::Mul, vec![a, b])) +// })) +// } +// _ => unreachable!() +// } +// } +// +// fn div_exprs<'a>(&self, exprs: &[Expr<'a>]) -> Result> { +// match exprs { +// [a, b] => { +// let a = self.visit_expr(a)?; +// let b = self.visit_expr(b)?; +// if a == Const(Null) || b == Const(Null) { +// return Ok(Const(Null)); +// } +// Ok(Const(match (a, b) { +// (Const(a), Const(b)) => { +// match (a, b) { +// (Int(va), Int(vb)) => Float(va as f64 / vb as f64), +// (Float(va), Int(vb)) => Float(va / vb as f64), +// (Int(va), Float(vb)) => Float(va as f64 / vb), +// (Float(va), Float(vb)) => Float(va / vb), +// (_, _) => return Err(CozoError::TypeError) +// } +// } +// (a, b) => return Ok(Apply(Op::Div, vec![a, b])) +// })) +// } +// _ => unreachable!() +// } +// } +// +// fn mod_exprs<'a>(&self, exprs: &[Expr<'a>]) -> Result> { +// match exprs { +// [a, b] => { +// let a = self.visit_expr(a)?; +// let b = self.visit_expr(b)?; +// if a == Const(Null) || b == Const(Null) { +// return Ok(Const(Null)); +// } +// Ok(Const(match (a, b) { +// (Const(a), Const(b)) => { +// match (a, b) { +// (Int(a), Int(b)) => Int(a % b), +// (_, _) => return Err(CozoError::TypeError) +// } +// } +// (a, b) => return Ok(Apply(Op::Mod, vec![a, b])) +// })) +// } +// _ => unreachable!() +// } +// } +// +// fn eq_exprs<'a>(&self, exprs: &[Expr<'a>]) -> Result> { +// match exprs { +// [a, b] => { +// let a = self.visit_expr(a)?; +// let b = self.visit_expr(b)?; +// if a == Const(Null) || b == Const(Null) { +// return Ok(Const(Null)); +// } +// match (a, b) { +// (Const(a), Const(b)) => Ok(Const(Bool(a == b))), +// (a, b) => Ok(Apply(Op::Eq, vec![a, b])) +// } +// } +// _ => unreachable!() +// } +// } +// +// fn ne_exprs<'a>(&self, exprs: &[Expr<'a>]) -> Result> { +// match exprs { +// [a, b] => { +// let a = self.visit_expr(a)?; +// let b = self.visit_expr(b)?; +// if a == Const(Null) || b == Const(Null) { +// return Ok(Const(Null)); +// } +// match (a, b) { +// (Const(a), Const(b)) => Ok(Const(Bool(a != b))), +// (a, b) => Ok(Apply(Op::Neq, vec![a, b])) +// } +// } +// _ => unreachable!() +// } +// } +// +// fn gt_exprs<'a>(&self, exprs: &[Expr<'a>]) -> Result> { +// match exprs { +// [a, b] => { +// let a = self.visit_expr(a)?; +// let b = self.visit_expr(b)?; +// if a == Const(Null) || b == Const(Null) { +// return Ok(Const(Null)); +// } +// match (a, b) { +// (Const(a), Const(b)) => { +// match (a, b) { +// (Int(a), Int(b)) => Ok(Const(Bool(a > b))), +// (Float(a), Int(b)) => Ok(Const(Bool(a > b as f64))), +// (Int(a), Float(b)) => Ok(Const(Bool(a as f64 > b))), +// (Float(a), Float(b)) => Ok(Const(Bool(a > b))), +// (_, _) => Err(CozoError::TypeError) +// } +// } +// (a, b) => Ok(Apply(Op::Gt, vec![a, b])) +// } +// } +// _ => unreachable!() +// } +// } +// +// fn ge_exprs<'a>(&self, exprs: &[Expr<'a>]) -> Result> { +// match exprs { +// [a, b] => { +// let a = self.visit_expr(a)?; +// let b = self.visit_expr(b)?; +// if a == Const(Null) || b == Const(Null) { +// return Ok(Const(Null)); +// } +// match (a, b) { +// (Const(a), Const(b)) => { +// match (a, b) { +// (Int(a), Int(b)) => Ok(Const(Bool(a >= b))), +// (Float(a), Int(b)) => Ok(Const(Bool(a >= b as f64))), +// (Int(a), Float(b)) => Ok(Const(Bool(a as f64 >= b))), +// (Float(a), Float(b)) => Ok(Const(Bool(a >= b))), +// (_, _) => Err(CozoError::TypeError) +// } +// } +// (a, b) => Ok(Apply(Op::Ge, vec![a, b])) +// } +// } +// _ => unreachable!() +// } +// } +// +// fn lt_exprs<'a>(&self, exprs: &[Expr<'a>]) -> Result> { +// match exprs { +// [a, b] => { +// let a = self.visit_expr(a)?; +// let b = self.visit_expr(b)?; +// if a == Const(Null) || b == Const(Null) { +// return Ok(Const(Null)); +// } +// match (a, b) { +// (Const(a), Const(b)) => { +// match (a, b) { +// (Int(a), Int(b)) => Ok(Const(Bool(a < b))), +// (Float(a), Int(b)) => Ok(Const(Bool(a < b as f64))), +// (Int(a), Float(b)) => Ok(Const(Bool((a as f64) < b))), +// (Float(a), Float(b)) => Ok(Const(Bool(a < b))), +// (_, _) => Err(CozoError::TypeError) +// } +// } +// (a, b) => Ok(Apply(Op::Lt, vec![a, b])) +// } +// } +// _ => unreachable!() +// } +// } +// +// fn le_exprs<'a>(&self, exprs: &[Expr<'a>]) -> Result> { +// match exprs { +// [a, b] => { +// let a = self.visit_expr(a)?; +// let b = self.visit_expr(b)?; +// if a == Const(Null) || b == Const(Null) { +// return Ok(Const(Null)); +// } +// match (a, b) { +// (Const(a), Const(b)) => { +// match (a, b) { +// (Int(a), Int(b)) => Ok(Const(Bool(a <= b))), +// (Float(a), Int(b)) => Ok(Const(Bool(a <= b as f64))), +// (Int(a), Float(b)) => Ok(Const(Bool((a as f64) <= b))), +// (Float(a), Float(b)) => Ok(Const(Bool(a <= b))), +// (_, _) => Err(CozoError::TypeError) +// } +// } +// (a, b) => Ok(Apply(Op::Le, vec![a, b])) +// } +// } +// _ => unreachable!() +// } +// } +// +// fn pow_exprs<'a>(&self, exprs: &[Expr<'a>]) -> Result> { +// match exprs { +// [a, b] => { +// let a = self.visit_expr(a)?; +// let b = self.visit_expr(b)?; +// if a == Const(Null) || b == Const(Null) { +// return Ok(Const(Null)); +// } +// match (a, b) { +// (Const(a), Const(b)) => { +// match (a, b) { +// (Int(a), Int(b)) => Ok(Const(Float((a as f64).powf(b as f64)))), +// (Float(a), Int(b)) => Ok(Const(Float(a.powi(b as i32)))), +// (Int(a), Float(b)) => Ok(Const(Float((a as f64).powf(b)))), +// (Float(a), Float(b)) => Ok(Const(Float(a.powf(b)))), +// (_, _) => Err(CozoError::TypeError) +// } +// } +// (a, b) => Ok(Apply(Op::Pow, vec![a, b])) +// } +// } +// _ => unreachable!() +// } +// } +// +// fn coalesce_exprs<'a>(&self, exprs: &[Expr<'a>]) -> Result> { +// match exprs { +// [a, b] => { +// let a = self.visit_expr(a)?; +// let b = self.visit_expr(b)?; +// if a == Const(Null) { +// return Ok(b); +// } +// if b == Const(Null) { +// return Ok(a); +// } +// if let a @ Const(_) = a { +// return Ok(a); +// } +// return Ok(Apply(Op::Coalesce, vec![a, b])); +// } +// _ => unreachable!() +// } +// } +// +// fn negate_expr<'a>(&self, exprs: &[Expr<'a>]) -> Result> { +// Ok(match exprs { +// [a] => { +// match self.visit_expr(a)? { +// Const(Null) => Const(Null), +// Const(Bool(b)) => Const(Bool(!b)), +// Const(_) => return Err(TypeError), +// Apply(Op::Neg, v) => v.into_iter().next().unwrap(), +// Apply(Op::IsNull, v) => Apply(Op::NotNull, v), +// Apply(Op::NotNull, v) => Apply(Op::IsNull, v), +// Apply(Op::Eq, v) => Apply(Op::Neq, v), +// Apply(Op::Neq, v) => Apply(Op::Eq, v), +// Apply(Op::Gt, v) => Apply(Op::Le, v), +// Apply(Op::Ge, v) => Apply(Op::Lt, v), +// Apply(Op::Le, v) => Apply(Op::Gt, v), +// Apply(Op::Lt, v) => Apply(Op::Ge, v), +// v => Apply(Op::Neg, vec![v]) +// } +// } +// _ => unreachable!() +// }) +// } +// +// fn minus_expr<'a>(&self, exprs: &[Expr<'a>]) -> Result> { +// Ok(match exprs { +// [a] => { +// match self.visit_expr(a)? { +// Const(Null) => Const(Null), +// Const(Int(i)) => Const(Int(-i)), +// Const(Float(f)) => Const(Float(-f)), +// Const(_) => return Err(TypeError), +// Apply(Op::Minus, v) => v.into_iter().next().unwrap(), +// v => Apply(Op::Minus, vec![v]) +// } +// } +// _ => unreachable!() +// }) +// } +// +// fn test_null_expr<'a>(&self, exprs: &[Expr<'a>]) -> Result> { +// Ok(match exprs { +// [a] => { +// match self.visit_expr(a)? { +// Const(Null) => Const(Bool(true)), +// Const(_) => Const(Bool(false)), +// v => Apply(Op::IsNull, vec![v]) +// } +// } +// _ => unreachable!() +// }) +// } +// +// fn not_null_expr<'a>(&self, exprs: &[Expr<'a>]) -> Result> { +// Ok(match exprs { +// [a] => { +// match self.visit_expr(a)? { +// Const(Null) => Const(Bool(false)), +// Const(_) => Const(Bool(true)), +// v => Apply(Op::IsNull, vec![v]) +// } +// } +// _ => unreachable!() +// }) +// } +// +// fn or_expr<'a>(&self, exprs: &[Expr<'a>]) -> Result> { +// let mut unevaluated = vec![]; +// let mut has_null = false; +// for expr in exprs { +// match self.visit_expr(expr)? { +// Const(Bool(true)) => return Ok(Const(Bool(true))), +// Const(Bool(false)) => {} +// Const(Null) => { has_null = true } +// Const(_) => return Err(TypeError), +// Apply(Op::Or, vs) => { +// for el in vs { +// match el { +// Const(Null) => has_null = true, +// Const(_) => unreachable!(), +// v => unevaluated.push(v) +// } +// } +// } +// v => unevaluated.push(v) +// } +// } +// match (has_null, unevaluated.len()) { +// (true, 0) => Ok(Const(Null)), +// (false, 0) => Ok(Const(Bool(false))), +// (false, _) => Ok(Apply(Op::Or, unevaluated)), +// (true, _) => { +// unevaluated.push(Const(Null)); +// Ok(Apply(Op::Or, unevaluated)) +// } +// } +// } +// +// fn and_expr<'a>(&self, exprs: &[Expr<'a>]) -> Result> { +// let mut unevaluated = vec![]; +// let mut no_null = true; +// for expr in exprs { +// match self.visit_expr(expr)? { +// Const(Bool(false)) => return Ok(Const(Bool(false))), +// Const(Bool(true)) => {} +// Const(Null) => no_null = false, +// Const(_) => return Err(TypeError), +// Apply(Op::Or, vs) => { +// for el in vs { +// match el { +// Const(Null) => no_null = false, +// Const(_) => unreachable!(), +// v => unevaluated.push(v) +// } +// } +// } +// v => unevaluated.push(v) +// } +// } +// match (no_null, unevaluated.len()) { +// (true, 0) => Ok(Const(Bool(true))), +// (false, 0) => Ok(Const(Null)), +// (true, _) => Ok(Apply(Op::Add, unevaluated)), +// (false, _) => { +// unevaluated.push(Const(Null)); +// Ok(Apply(Op::And, unevaluated)) +// } +// } +// } +// } +// +// #[cfg(test)] +// mod tests { +// use super::*; +// +// #[test] +// fn operators() { +// let ev = Evaluator::new(DummyStorage {}).unwrap(); +// +// println!("{:#?}", ev.visit_expr(&parse_expr_from_str("1/10+(-2+3)*4^5").unwrap()).unwrap()); +// println!("{:#?}", ev.visit_expr(&parse_expr_from_str("true && false").unwrap()).unwrap()); +// println!("{:#?}", ev.visit_expr(&parse_expr_from_str("true || false").unwrap()).unwrap()); +// println!("{:#?}", ev.visit_expr(&parse_expr_from_str("true || null").unwrap()).unwrap()); +// println!("{:#?}", ev.visit_expr(&parse_expr_from_str("null || true").unwrap()).unwrap()); +// println!("{:#?}", ev.visit_expr(&parse_expr_from_str("true && null").unwrap()).unwrap()); +// } +// } \ No newline at end of file diff --git a/src/function.rs b/src/function.rs index 35e2ac6f..5ddb66dd 100644 --- a/src/function.rs +++ b/src/function.rs @@ -1,72 +1,72 @@ -use std::fmt::{Debug, Formatter}; -use crate::typing::{Typing}; -use crate::value::{StaticValue, Value}; -// use lazy_static::lazy_static; - -#[derive(PartialEq, Debug)] -pub struct Function { - pub args: Vec, - pub var_arg: Option, - pub ret_type: Typing, - pub fn_impl: FunctionImpl, -} - -pub enum FunctionImpl { - Native(&'static str, for<'a> fn(&[Value<'a>]) -> Value<'a>), - UserDefined(()), -} - -impl Debug for FunctionImpl { - fn fmt(&self, _f: &mut Formatter<'_>) -> std::fmt::Result { - todo!() - } -} - -impl PartialEq for FunctionImpl { - fn eq(&self, other: &Self) -> bool { - match (self, other) { - (FunctionImpl::Native(a,_), FunctionImpl::Native(b,_)) => a == b, - (FunctionImpl::UserDefined(a), FunctionImpl::UserDefined(b)) => a == b, - (_, _) => false - } - } -} - -#[derive(PartialEq, Debug)] -pub struct Arg { - pub typing: Typing, - pub default_val: Option, - pub name: Option, -} - -// lazy_static! { -// static ref BUILT_IN_FUNCTIONS : BTreeMap<&'static str, Function> = { -// let mut ret = BTreeMap::new(); +// use std::fmt::{Debug, Formatter}; +// use crate::typing::{Typing}; +// use crate::value::{StaticValue, Value}; +// // use lazy_static::lazy_static; // -// fn add_int<'a>(_args: &[Value<'a>]) -> Value<'a> { -// todo!() -// } +// #[derive(PartialEq, Debug)] +// pub struct Function { +// pub args: Vec, +// pub var_arg: Option, +// pub ret_type: Typing, +// pub fn_impl: FunctionImpl, +// } // -// fn add_float<'a>(_args: &[Value<'a>]) -> Value<'a> { -// todo!() -// } +// pub enum FunctionImpl { +// Native(&'static str, for<'a> fn(&[Value<'a>]) -> Value<'a>), +// UserDefined(()), +// } // -// ret.insert("_add_int", -// Function { -// args: vec![], -// var_arg: Some(Typing::Base(BaseType::Int)), -// ret_type: Typing::Base(BaseType::Int), -// fn_impl: FunctionImpl::Native("_add_int", add_int) -// }); +// impl Debug for FunctionImpl { +// fn fmt(&self, _f: &mut Formatter<'_>) -> std::fmt::Result { +// todo!() +// } +// } // -// ret.insert("_add_float", -// Function { -// args: vec![], -// var_arg: Some(Typing::Base(BaseType::Float)), -// ret_type: Typing::Base(BaseType::Float), -// fn_impl: FunctionImpl::Native("_add_float", add_float) -// }); +// impl PartialEq for FunctionImpl { +// fn eq(&self, other: &Self) -> bool { +// match (self, other) { +// (FunctionImpl::Native(a,_), FunctionImpl::Native(b,_)) => a == b, +// (FunctionImpl::UserDefined(a), FunctionImpl::UserDefined(b)) => a == b, +// (_, _) => false +// } +// } +// } // -// ret -// }; +// #[derive(PartialEq, Debug)] +// pub struct Arg { +// pub typing: Typing, +// pub default_val: Option, +// pub name: Option, // } +// +// // lazy_static! { +// // static ref BUILT_IN_FUNCTIONS : BTreeMap<&'static str, Function> = { +// // let mut ret = BTreeMap::new(); +// // +// // fn add_int<'a>(_args: &[Value<'a>]) -> Value<'a> { +// // todo!() +// // } +// // +// // fn add_float<'a>(_args: &[Value<'a>]) -> Value<'a> { +// // todo!() +// // } +// // +// // ret.insert("_add_int", +// // Function { +// // args: vec![], +// // var_arg: Some(Typing::Base(BaseType::Int)), +// // ret_type: Typing::Base(BaseType::Int), +// // fn_impl: FunctionImpl::Native("_add_int", add_int) +// // }); +// // +// // ret.insert("_add_float", +// // Function { +// // args: vec![], +// // var_arg: Some(Typing::Base(BaseType::Float)), +// // ret_type: Typing::Base(BaseType::Float), +// // fn_impl: FunctionImpl::Native("_add_float", add_float) +// // }); +// // +// // ret +// // }; +// // } diff --git a/src/lib.rs b/src/lib.rs index 82118271..5333266b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,5 @@ +extern crate core; + pub mod value; pub mod typing; pub mod env; @@ -9,4 +11,5 @@ pub mod error; pub mod definition; pub mod storage; pub mod mutation; -pub mod plan; \ No newline at end of file +pub mod plan; +pub mod relation; \ No newline at end of file diff --git a/src/mutation.rs b/src/mutation.rs index 3362b871..7fabface 100644 --- a/src/mutation.rs +++ b/src/mutation.rs @@ -1,97 +1,97 @@ -use std::borrow::Borrow; -use std::collections::BTreeMap; -use pest::iterators::Pair; -use crate::ast::{build_expr, Expr, ExprVisitor}; -use crate::definition::build_name_in_def; -use crate::env::Env; -use crate::error::CozoError::{IncompatibleValue, UndefinedTable, ValueRequired}; -use crate::eval::Evaluator; -use crate::storage::{RocksStorage}; -use crate::error::Result; -use crate::parser::{Parser, Rule}; -use crate::typing::Structured; -use crate::value::Value; - -impl Evaluator { - pub fn eval_mutation(&mut self, pair: Pair) -> Result<()> { - let mut pairs = pair.into_inner(); - let op = pairs.next().unwrap().as_rule(); - let expr = pairs.next().unwrap(); - let main_target; - // let filters; - match pairs.next() { - None => { - main_target = None; - // filters = None; - } - Some(v) => { - match v.as_rule() { - Rule::name_in_def => { - // let resolved = self.resolve(&build_name_in_def(v, true)?) - // .ok_or(UndefinedTable)?.borrow(); - // main_target = Some(resolved); - todo!() - } - Rule::mutation_filter => { - main_target = None; - todo!() - } - _ => unreachable!() - } - } - } - let expr = build_expr(expr)?; - let expr = self.visit_expr(&expr)?; - let val = match expr { - Expr::Const(v) => v, - _ => return Err(ValueRequired) - }; - let val = val.get_list().ok_or(IncompatibleValue)?; - println!("{:#?}", val); - let coerced_values = self.coerce_table_values(&val, main_target); - Ok(()) - } - - fn coerce_table_values(&self, values: &[Value], default_table: Option<&Structured>) -> BTreeMap<&Structured, Vec> { - todo!() - } -} - - -#[cfg(test)] -mod tests { - use std::fs; - use super::*; - use crate::ast::{Expr, ExprVisitor, parse_expr_from_str}; - use pest::Parser as PestParser; - use crate::env::Env; - use crate::storage::DummyStorage; - use crate::typing::Structured; - - #[test] - fn data() -> Result<()> { - let ddl = fs::read_to_string("test_data/hr.cozo")?; - let parsed = Parser::parse(Rule::file, &ddl).unwrap(); - let db = RocksStorage::new("_path_hr".to_string())?; - let mut eval = Evaluator::new(db).unwrap(); - eval.build_table(parsed).unwrap(); - eval.restore_metadata().unwrap(); - - let insertion = "insert $data;"; - let mut insert_stmt = Parser::parse(Rule::mutation, insertion).unwrap(); - - let data = fs::read_to_string("test_data/hr.json")?; - let parsed = parse_expr_from_str(&data)?; - let ev = Evaluator::new(DummyStorage {})?; - let evaluated = ev.visit_expr(&parsed)?; - let bound_value = match evaluated { - Expr::Const(v) => v, - _ => unreachable!() - }; - - eval.define("$data".to_string(), Structured::Value(bound_value.owned_clone())); - eval.eval_mutation(insert_stmt.next().unwrap()).unwrap(); - // println!("{:#?}", evaluated); - Ok(()) - } -} \ No newline at end of file +// use std::borrow::Borrow; +// use std::collections::BTreeMap; +// use pest::iterators::Pair; +// use crate::ast::{build_expr, Expr, ExprVisitor}; +// use crate::definition::build_name_in_def; +// use crate::env::Env; +// use crate::error::CozoError::{IncompatibleValue, UndefinedTable, ValueRequired}; +// use crate::eval::Evaluator; +// use crate::storage::{RocksStorage}; +// use crate::error::Result; +// use crate::parser::{Parser, Rule}; +// use crate::typing::Structured; +// use crate::value::Value; +// +// impl Evaluator { +// pub fn eval_mutation(&mut self, pair: Pair) -> Result<()> { +// let mut pairs = pair.into_inner(); +// let op = pairs.next().unwrap().as_rule(); +// let expr = pairs.next().unwrap(); +// let main_target; +// // let filters; +// match pairs.next() { +// None => { +// main_target = None; +// // filters = None; +// } +// Some(v) => { +// match v.as_rule() { +// Rule::name_in_def => { +// // let resolved = self.resolve(&build_name_in_def(v, true)?) +// // .ok_or(UndefinedTable)?.borrow(); +// // main_target = Some(resolved); +// todo!() +// } +// Rule::mutation_filter => { +// main_target = None; +// todo!() +// } +// _ => unreachable!() +// } +// } +// } +// let expr = build_expr(expr)?; +// let expr = self.visit_expr(&expr)?; +// let val = match expr { +// Expr::Const(v) => v, +// _ => return Err(ValueRequired) +// }; +// let val = val.get_list().ok_or(IncompatibleValue)?; +// println!("{:#?}", val); +// let coerced_values = self.coerce_table_values(&val, main_target); +// Ok(()) +// } +// +// fn coerce_table_values(&self, values: &[Value], default_table: Option<&Structured>) -> BTreeMap<&Structured, Vec> { +// todo!() +// } +// } +// +// +// #[cfg(test)] +// mod tests { +// use std::fs; +// use super::*; +// use crate::ast::{Expr, ExprVisitor, parse_expr_from_str}; +// use pest::Parser as PestParser; +// use crate::env::Env; +// use crate::storage::DummyStorage; +// use crate::typing::Structured; +// +// #[test] +// fn data() -> Result<()> { +// let ddl = fs::read_to_string("test_data/hr.cozo")?; +// let parsed = Parser::parse(Rule::file, &ddl).unwrap(); +// let db = RocksStorage::new("_path_hr".to_string())?; +// let mut eval = Evaluator::new(db).unwrap(); +// eval.build_table(parsed).unwrap(); +// eval.restore_metadata().unwrap(); +// +// let insertion = "insert $data;"; +// let mut insert_stmt = Parser::parse(Rule::mutation, insertion).unwrap(); +// +// let data = fs::read_to_string("test_data/hr.json")?; +// let parsed = parse_expr_from_str(&data)?; +// let ev = Evaluator::new(DummyStorage {})?; +// let evaluated = ev.visit_expr(&parsed)?; +// let bound_value = match evaluated { +// Expr::Const(v) => v, +// _ => unreachable!() +// }; +// +// eval.define("$data".to_string(), Structured::Value(bound_value.owned_clone())); +// eval.eval_mutation(insert_stmt.next().unwrap()).unwrap(); +// // println!("{:#?}", evaluated); +// Ok(()) +// } +// } \ No newline at end of file diff --git a/src/relation.rs b/src/relation.rs new file mode 100644 index 00000000..851c5f60 --- /dev/null +++ b/src/relation.rs @@ -0,0 +1 @@ +pub mod tuple; \ No newline at end of file diff --git a/src/relation/tuple.rs b/src/relation/tuple.rs new file mode 100644 index 00000000..185c2f3a --- /dev/null +++ b/src/relation/tuple.rs @@ -0,0 +1,579 @@ +use std::borrow::{Cow}; +use std::cell::RefCell; +use std::cmp::Ordering; +use std::collections::BTreeMap; +use uuid::Uuid; + +#[repr(u8)] +#[derive(Ord, PartialOrd, Eq, PartialEq)] +pub enum Tag { + BoolFalse = 0, + Null = 2, + BoolTrue = 4, + FwdEdge = 6, + BwdEdge = 8, + Int = 11, + Float = 13, + Text = 15, + Uuid = 17, + UInt = 21, + List = 101, + Dict = 103, + // Timestamp = 23, + // Datetime = 25, + // Timezone = 27, + // Date = 27, + // Time = 29, + // Duration = 31, + // BigInt = 51, + // BigDecimal = 53, + // Inet = 55, + // Crs = 57, + // BitArr = 60, + // U8Arr = 61, + // I8Arr = 62, + // U16Arr = 63, + // I16Arr = 64, + // U32Arr = 65, + // I32Arr = 66, + // U64Arr = 67, + // I64Arr = 68, + // F16Arr = 69, + // F32Arr = 70, + // F64Arr = 71, + // C32Arr = 72, + // C64Arr = 73, + // C128Arr = 74, +} + +impl From for Tag { + fn from(u: u8) -> Self { + use self::Tag::*; + match u { + 0 => BoolFalse, + 2 => Null, + 4 => BoolTrue, + 6 => FwdEdge, + 8 => BwdEdge, + 11 => Int, + 13 => Float, + 15 => Text, + 17 => Uuid, + 21 => UInt, + 101 => List, + 103 => Dict, + _ => panic!("Unexpected value tag {}", u) + } + } +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum EdgeDir { + Fwd, + Bwd, +} + + +#[derive(Debug, Clone, PartialEq)] +pub enum Value<'a> { + Null, + Bool(bool), + EdgeDir(EdgeDir), + UInt(u64), + Int(i64), + Float(f64), + Uuid(Uuid), + Text(Cow<'a, str>), + List(Vec>), + Dict(BTreeMap, Value<'a>>), +} + +impl From<()> for Value<'static> { + fn from(_: ()) -> Self { + Value::Null + } +} + +impl From for Value<'static> { + fn from(b: bool) -> Self { + Value::Bool(b) + } +} + +impl From for Value<'static> { + fn from(e: EdgeDir) -> Self { + Value::EdgeDir(e) + } +} + +impl From for Value<'static> { + fn from(u: u64) -> Self { + Value::UInt(u) + } +} + +impl From for Value<'static> { + fn from(i: i64) -> Self { + Value::Int(i) + } +} + +impl From for Value<'static> { + fn from(f: f64) -> Self { + Value::Float(f) + } +} + +impl<'a> From<&'a str> for Value<'a> { + fn from(s: &'a str) -> Self { + Value::Text(Cow::Borrowed(s)) + } +} + +impl From for Value<'static> { + fn from(s: String) -> Self { + Value::Text(Cow::Owned(s)) + } +} + +impl From for Value<'static> { + fn from(u: Uuid) -> Self { + Value::Uuid(u) + } +} + +impl<'a> From>> for Value<'a> { + fn from(v: Vec>) -> Self { + Value::List(v) + } +} + +impl<'a> From, Value<'a>>> for Value<'a> { + fn from(m: BTreeMap, Value<'a>>) -> Self { + Value::Dict(m) + } +} + +pub type StaticValue = Value<'static>; + +#[derive(Debug, Clone)] +pub struct Tuple + where T: AsRef<[u8]> +{ + pub data: T, + idx_cache: RefCell>, +} + +const PREFIX_LEN: usize = 4; + +impl> Tuple { + fn new(data: T) -> Self { + Self { + data, + idx_cache: RefCell::new(vec![]), + } + } + + #[inline] + fn all_cached(&self) -> bool { + match self.idx_cache.borrow().last() { + None => self.data.as_ref().len() == PREFIX_LEN, + Some(l) => *l == self.data.as_ref().len() + } + } + #[inline] + fn get_pos(&self, idx: usize) -> Option { + if idx == 0 { + if self.data.as_ref().len() > PREFIX_LEN { + Some(PREFIX_LEN) + } else { + None + } + } else { + self.cache_until(idx); + self.idx_cache.borrow().get(idx - 1).cloned() + } + } + #[inline] + fn cache_until(&self, idx: usize) { + while self.idx_cache.borrow().len() < idx && !self.all_cached() { + self.skip_and_cache(); + } + } + #[inline] + fn skip_and_cache(&self) { + let data = self.data.as_ref(); + let tag_start = *self.idx_cache.borrow().last().unwrap_or(&PREFIX_LEN); + let start = tag_start + 1; + let nxt = match Tag::from(data[tag_start]) { + Tag::Null | Tag::BoolTrue | Tag::BoolFalse | Tag::FwdEdge | Tag::BwdEdge => start, + Tag::Int | Tag::UInt => start + self.parse_varint(start).1, + Tag::Float => start + 8, + Tag::Uuid => start + 16, + Tag::Text => { + let (slen, offset) = self.parse_varint(start); + let slen = slen as usize; + start + slen + offset + } + Tag::List => start + u32::from_be_bytes(data[start..start + 4].try_into().unwrap()) as usize, + Tag::Dict => start + u32::from_be_bytes(data[start..start + 4].try_into().unwrap()) as usize + }; + self.idx_cache.borrow_mut().push(nxt); + } + + #[inline] + fn parse_varint(&self, idx: usize) -> (u64, usize) { + let data = self.data.as_ref(); + let mut cur = idx; + let mut u: u64 = 0; + let mut shift = 0; + loop { + let buf = data[cur]; + cur += 1; + u |= ((buf & 0b01111111) as u64) << shift; + if buf & 0b10000000 == 0 { + break; + } + shift += 7; + } + (u, cur - idx) + } + + pub fn get(&self, idx: usize) -> Option { + match self.get_pos(idx) { + Some(v) => { + if v == self.data.as_ref().len() { + return None; + } + let (val, nxt) = self.parse_value_at(v); + if idx == self.idx_cache.borrow().len() { + self.idx_cache.borrow_mut().push(nxt); + } + Some(val) + } + None => None + } + } + pub 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]) { + Tag::Null => (start, ().into()), + Tag::BoolTrue => (start, true.into()), + Tag::BoolFalse => (start, false.into()), + Tag::FwdEdge => (start, EdgeDir::Fwd.into()), + Tag::BwdEdge => (start, EdgeDir::Bwd.into()), + Tag::UInt => { + let (u, offset) = self.parse_varint(start); + (start + offset, u.into()) + } + Tag::Int => { + let (u, offset) = self.parse_varint(start); + let val = if u & 1 == 0 { + (u >> 1) as i64 + } else { + -((u >> 1) as i64) - 1 + }; + (start + offset, val.into()) + } + Tag::Float => (start + 8, f64::from_be_bytes(data[start..start + 8].try_into().unwrap()).into()), + Tag::Uuid => (start + 16, Uuid::from_slice(&data[start..start + 16]).unwrap().into()), + Tag::Text => { + let (slen, offset) = self.parse_varint(start); + let slen = slen as usize; + let s = unsafe { + std::str::from_utf8_unchecked(&data[start + offset..start + offset + slen]) + }; + + (start + slen + offset, s.into()) + } + Tag::List => { + let end_pos = start + u32::from_be_bytes(data[start..start + 4].try_into().unwrap()) as usize; + let mut start_pos = start + 4; + let mut collected = vec![]; + while start_pos < end_pos { + let (val, new_pos) = self.parse_value_at(start_pos); + collected.push(val); + start_pos = new_pos; + } + (end_pos, collected.into()) + } + Tag::Dict => { + let end_pos = start + u32::from_be_bytes(data[start..start + 4].try_into().unwrap()) as usize; + let mut start_pos = start + 4; + let mut collected: BTreeMap, Value> = BTreeMap::new(); + while start_pos < end_pos { + let (slen, offset) = self.parse_varint(start_pos); + start_pos += offset; + let key = unsafe { + std::str::from_utf8_unchecked(&data[start_pos..start_pos + slen as usize]) + }; + start_pos += slen as usize; + let (val, new_pos) = self.parse_value_at(start_pos); + collected.insert(key.into(), val); + start_pos = new_pos; + } + (end_pos, collected.into()) + } + }; + (val, nxt) + } +} + +impl Tuple<&[u8]> {} + + +impl Tuple> { + pub fn with_prefix(prefix: u32) -> Self { + let data = Vec::from(prefix.to_be_bytes()); + Self { + data, + idx_cache: RefCell::new(vec![]), + } + } + #[inline] + fn push_tag(&mut self, tag: Tag) { + self.data.push(tag as u8); + } + #[inline] + pub fn push_null(&mut self) { + self.push_tag(Tag::Null); + self.idx_cache.borrow_mut().push(self.data.len()); + } + #[inline] + pub fn push_bool(&mut self, b: bool) { + self.push_tag(if b { Tag::BoolTrue } else { Tag::BoolFalse }); + self.idx_cache.borrow_mut().push(self.data.len()); + } + #[inline] + pub fn push_edge_dir(&mut self, d: EdgeDir) { + self.push_tag(match d { + EdgeDir::Fwd => { Tag::FwdEdge } + EdgeDir::Bwd => { Tag::BwdEdge } + }); + self.idx_cache.borrow_mut().push(self.data.len()); + } + #[inline] + pub fn push_int(&mut self, i: i64) { + self.push_tag(Tag::Int); + self.push_zigzag(i); + self.idx_cache.borrow_mut().push(self.data.len()); + } + #[inline] + pub fn push_float(&mut self, f: f64) { + self.push_tag(Tag::Float); + self.data.extend(f.to_be_bytes()); + self.idx_cache.borrow_mut().push(self.data.len()); + } + #[inline] + pub fn push_uint(&mut self, u: u64) { + self.push_tag(Tag::UInt); + self.push_varint(u); + self.idx_cache.borrow_mut().push(self.data.len()); + } + #[inline] + pub fn push_uuid(&mut self, u: Uuid) { + self.push_tag(Tag::Uuid); + self.data.extend(u.as_bytes()); + self.idx_cache.borrow_mut().push(self.data.len()); + } + #[inline] + pub fn push_str(&mut self, s: impl AsRef) { + let s = s.as_ref(); + self.push_tag(Tag::Text); + self.push_varint(s.len() as u64); + self.data.extend_from_slice(s.as_bytes()); + self.idx_cache.borrow_mut().push(self.data.len()); + } + pub fn push_value(&mut self, v: &Value) { + match v { + Value::Null => self.push_null(), + Value::Bool(b) => self.push_bool(*b), + 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::Uuid(u) => self.push_uuid(*u), + Value::Text(t) => self.push_str(t), + Value::List(l) => { + self.push_tag(Tag::List); + let start_pos = self.data.len(); + let start_len = self.idx_cache.borrow().len(); + self.data.extend(0u32.to_be_bytes()); + for val in l { + self.push_value(val); + } + let length = (self.data.len() - start_pos) as u32; + let length_bytes = length.to_be_bytes(); + for i in 0..4 { + self.data[start_pos + i] = length_bytes[i] + } + let mut cache = self.idx_cache.borrow_mut(); + cache.truncate(start_len); + cache.push(self.data.len()); + } + Value::Dict(d) => { + self.push_tag(Tag::Dict); + let start_pos = self.data.len(); + let start_len = self.idx_cache.borrow().len(); + self.data.extend(0u32.to_be_bytes()); + for (k, v) in d { + self.push_varint(k.len() as u64); + self.data.extend_from_slice(k.as_bytes()); + self.push_value(v); + } + let length = (self.data.len() - start_pos) as u32; + let length_bytes = length.to_be_bytes(); + for i in 0..4 { + self.data[start_pos + i] = length_bytes[i] + } + let mut cache = self.idx_cache.borrow_mut(); + cache.truncate(start_len); + cache.push(self.data.len()); + } + } + } + + + #[inline] + fn push_varint(&mut self, u: u64) { + let mut u = u; + while u > 0b01111111 { + self.data.push(0b10000000 | (u as u8 & 0b01111111)); + u >>= 7; + } + self.data.push(u as u8); + } + + #[inline] + fn push_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.push_varint(u); + } + +} + +impl> PartialEq for Tuple { + fn eq(&self, other: &Self) -> bool { + self.data.as_ref() == other.data.as_ref() + } +} + +impl> Eq for Tuple {} + +impl> PartialOrd for Tuple { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl> Ord for Tuple { + fn cmp(&self, other: &Self) -> Ordering { + todo!() + } +} + + +#[cfg(test)] +mod tests { + use std::collections::BTreeMap; + use crate::relation::tuple::{EdgeDir, Tuple, Value}; + + #[test] + fn serde() { + let mut t = Tuple::with_prefix(0); + t.push_null(); + t.push_bool(true); + t.push_bool(false); + t.push_edge_dir(EdgeDir::Fwd); + t.push_str("abcdef"); + t.push_edge_dir(EdgeDir::Bwd); + t.push_value(&vec![ + true.into(), + 1e236.into(), + "xxyyzz".into(), + ].into()); + t.push_int(-123345); + t.push_value(&BTreeMap::from([]).into()); + t.push_uint(12121212); + t.push_value(&BTreeMap::from([("yzyz".into(), "fifo".into())]).into()); + t.push_float(1e245); + t.push_bool(false); + assert!(t.all_cached()); + assert_eq!(t.idx_cache.borrow().len(), 13); + let ot = t; + let t = Tuple::new(ot.data.as_slice()); + let t3 = Tuple::new(ot.data.as_slice()); + assert_eq!(Value::from(()), t.get(0).unwrap()); + t3.get_pos(1); + assert_eq!(t.idx_cache.borrow().last(), t3.idx_cache.borrow().last()); + assert_eq!(Value::from(true), t.get(1).unwrap()); + t3.get_pos(2); + assert_eq!(t.idx_cache.borrow().last(), t3.idx_cache.borrow().last()); + assert_eq!(Value::from(false), t.get(2).unwrap()); + t3.get_pos(3); + assert_eq!(t.idx_cache.borrow().last(), t3.idx_cache.borrow().last()); + assert_eq!(Value::from(EdgeDir::Fwd), t.get(3).unwrap()); + t3.get_pos(4); + assert_eq!(t.idx_cache.borrow().last(), t3.idx_cache.borrow().last()); + assert_eq!(Value::from("abcdef"), t.get(4).unwrap()); + t3.get_pos(5); + assert_eq!(t.idx_cache.borrow().last(), t3.idx_cache.borrow().last()); + assert_eq!(Value::from(EdgeDir::Bwd), t.get(5).unwrap()); + t3.get_pos(6); + assert_eq!(t.idx_cache.borrow().last(), t3.idx_cache.borrow().last()); + assert_eq!(Value::from(Value::from(vec![ + true.into(), + 1e236.into(), + "xxyyzz".into(), + ])), t.get(6).unwrap()); + t3.get_pos(7); + assert_eq!(t.idx_cache.borrow().last(), t3.idx_cache.borrow().last()); + assert_eq!(Value::from(-123345i64), t.get(7).unwrap()); + t3.get_pos(8); + assert_eq!(t.idx_cache.borrow().last(), t3.idx_cache.borrow().last()); + assert_eq!(Value::from(BTreeMap::new()), t.get(8).unwrap()); + t3.get_pos(9); + assert_eq!(t.idx_cache.borrow().last(), t3.idx_cache.borrow().last()); + assert_eq!(Value::from(12121212u64), t.get(9).unwrap()); + t3.get_pos(10); + assert_eq!(t.idx_cache.borrow().last(), t3.idx_cache.borrow().last()); + assert_eq!(Value::from(BTreeMap::from([("yzyz".into(), "fifo".into())])), t.get(10).unwrap()); + t3.get_pos(11); + assert_eq!(t.idx_cache.borrow().last(), t3.idx_cache.borrow().last()); + assert_eq!(Value::from(1e245), t.get(11).unwrap()); + t3.get_pos(12); + assert_eq!(t.idx_cache.borrow().last(), t3.idx_cache.borrow().last()); + assert_eq!(Value::from(false), t.get(12).unwrap()); + t3.get_pos(13); + assert_eq!(t.idx_cache.borrow().last(), t3.idx_cache.borrow().last()); + assert_eq!(None, t.get(13)); + assert_eq!(None, t.get(13131)); + let t = Tuple::new(ot.data.as_slice()); + assert_eq!(Value::from(EdgeDir::Bwd), t.get(5).unwrap()); + assert_eq!(Value::from(true), t.get(1).unwrap()); + assert_eq!(Value::from(true), t.get(1).unwrap()); + assert_eq!(Value::from(1e245), t.get(11).unwrap()); + assert_eq!(Value::from(false), t.get(12).unwrap()); + assert_eq!(Value::from(()), t.get(0).unwrap()); + assert_eq!(Value::from(false), t.get(2).unwrap()); + assert_eq!(Value::from(12121212u64), t.get(9).unwrap()); + assert_eq!(Value::from(BTreeMap::new()), t.get(8).unwrap()); + assert_eq!(Value::from(EdgeDir::Fwd), t.get(3).unwrap()); + assert_eq!(Value::from("abcdef"), t.get(4).unwrap()); + assert_eq!(Value::from(Value::from(vec![ + true.into(), + 1e236.into(), + "xxyyzz".into(), + ])), t.get(6).unwrap()); + assert_eq!(None, t.get(13)); + 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)); + } +} \ No newline at end of file diff --git a/src/storage.rs b/src/storage.rs index 4f92816d..930cf212 100644 --- a/src/storage.rs +++ b/src/storage.rs @@ -1,141 +1,141 @@ -use std::fs; -use std::sync::atomic::{AtomicUsize, Ordering}; -use std::sync::{RwLock}; -use crate::error::{CozoError, Result}; -use cozo_rocks::*; -use crate::env::Environment; -use crate::value::{cozo_comparator_v1}; - - -pub struct RocksStorage { - pub db: DB, - #[allow(dead_code)] - path: String, - last_local_id: AtomicUsize, - pub root_env: RwLock, -} - -const DEFAULT_CF: &str = "default"; -const SCRATCH_CF: &str = "scratch"; -const COMPARATOR_NAME: &str = "cozo_comparator_v1"; - -impl RocksStorage { - #[allow(unused_variables)] - pub fn new(path: String) -> Result { - let options = Options::default() - .increase_parallelism() - .optimize_level_style_compaction() - .set_create_if_missing(true) - .set_comparator(COMPARATOR_NAME, cozo_comparator_v1); - - let db = DB::open(options, path.as_ref())?; - (match db.create_column_family(SCRATCH_CF) { - Err(s) if s.bridge_code == StatusBridgeCode::EXISTING_ERROR => Ok(()), - v => v - })?; - let mut env = Environment::default(); - env.define_base_types(); - Ok(RocksStorage { - db, - path, - last_local_id: AtomicUsize::new(0), - root_env: RwLock::new(env), - }) - } - - #[allow(unused_variables)] - pub fn delete_storage(self) -> Result<()> { - let path = self.path.clone(); - drop(self); - fs::remove_dir_all(path)?; - Ok(()) - } - - #[allow(unused_variables)] - pub fn put_global(&self, k: &[u8], v: &[u8]) -> Result<()> { - let default_cf = self.db.get_cf_handle(DEFAULT_CF)?; - self.db.put(k, v, &default_cf, None)?; - - Ok(()) - } - #[allow(unused_variables)] - pub fn create_table(&self, name: &str, _global: bool) -> Result<()> { - match self.db.create_column_family(table_name_to_cf_name(name)) { - Ok(_) => Ok(()), - Err(s) if s.bridge_code == StatusBridgeCode::EXISTING_ERROR => Ok(()), - Err(e) => Err(CozoError::Storage(e)) - } - } - #[allow(unused_variables)] - pub fn drop_table(&self, name: &str, _global: bool) -> Result<()> { - self.db.drop_column_family(table_name_to_cf_name(name))?; - Ok(()) - } - - pub fn get_next_local_id(&self, global: bool) -> usize { - if global { - 0 - } else { - self.last_local_id.fetch_add(1, Ordering::Relaxed) + 1 - } - } -} - -#[inline] -fn table_name_to_cf_name(name: &str) -> String { - format!("${}", name) -} - -pub trait Storage {} - -pub struct DummyStorage; - -impl Storage for DummyStorage {} - -impl Storage for RocksStorage {} - -#[cfg(test)] -mod tests { - use std::str::from_utf8; - use crate::value::{ByteArrayBuilder, cozo_comparator_v1, Value}; - - #[test] - fn import() { - use cozo_rocks::*; - let options = Options::default() - .increase_parallelism() - .optimize_level_style_compaction() - .set_create_if_missing(true) - .set_comparator("cozo_comparator_v1", cozo_comparator_v1); - - let db = DB::open(options, - "xxyyzz.db".as_ref()).unwrap(); - - let mut builder = ByteArrayBuilder::default(); - builder.build_value(&Value::RefString("A key")); - let key = builder; - - let mut builder = ByteArrayBuilder::default(); - builder.build_value(&Value::RefString("Another key")); - let key2 = builder; - let cf = db.get_cf_handle("default").unwrap(); - println!("{:?}", db.all_cf_names()); - - let val = db.get(&key, &cf, None).unwrap(); - println!("before anything {}", val.is_none()); - - db.put(&key, "A motherfucking value!!! 👋👋👋", &cf, None).unwrap(); - let batch = WriteBatch::default(); - batch.put(&key2, "Another motherfucking value!!! 👋👋👋", &cf).unwrap(); - db.write(batch, None).unwrap(); - // db.put("Yes man", "A motherfucking value!!! 👋👋👋", None).unwrap(); - let val = db.get(&key, &cf, None).unwrap().unwrap(); - println!("1 {}", from_utf8(val.as_ref()).unwrap()); - let val = db.get(&key2, &cf, None).unwrap().unwrap(); - // let val = val.as_bytes(); - println!("2 {}", from_utf8(val.as_ref()).unwrap()); - let val = db.get(&key, &cf, None).unwrap().unwrap(); - println!("3 {}", from_utf8(val.as_ref()).unwrap()); - println!("4 {}", from_utf8(db.get(&key, &cf, None).unwrap().unwrap().as_ref()).unwrap()); - } -} \ No newline at end of file +// use std::fs; +// use std::sync::atomic::{AtomicUsize, Ordering}; +// use std::sync::{RwLock}; +// use crate::error::{CozoError, Result}; +// use cozo_rocks::*; +// use crate::env::Environment; +// use crate::value::{cozo_comparator_v1}; +// +// +// pub struct RocksStorage { +// pub db: DB, +// #[allow(dead_code)] +// path: String, +// last_local_id: AtomicUsize, +// pub root_env: RwLock, +// } +// +// const DEFAULT_CF: &str = "default"; +// const SCRATCH_CF: &str = "scratch"; +// const COMPARATOR_NAME: &str = "cozo_comparator_v1"; +// +// impl RocksStorage { +// #[allow(unused_variables)] +// pub fn new(path: String) -> Result { +// let options = Options::default() +// .increase_parallelism() +// .optimize_level_style_compaction() +// .set_create_if_missing(true) +// .set_comparator(COMPARATOR_NAME, cozo_comparator_v1); +// +// let db = DB::open(options, path.as_ref())?; +// (match db.create_column_family(SCRATCH_CF) { +// Err(s) if s.bridge_code == StatusBridgeCode::EXISTING_ERROR => Ok(()), +// v => v +// })?; +// let mut env = Environment::default(); +// env.define_base_types(); +// Ok(RocksStorage { +// db, +// path, +// last_local_id: AtomicUsize::new(0), +// root_env: RwLock::new(env), +// }) +// } +// +// #[allow(unused_variables)] +// pub fn delete_storage(self) -> Result<()> { +// let path = self.path.clone(); +// drop(self); +// fs::remove_dir_all(path)?; +// Ok(()) +// } +// +// #[allow(unused_variables)] +// pub fn put_global(&self, k: &[u8], v: &[u8]) -> Result<()> { +// let default_cf = self.db.get_cf_handle(DEFAULT_CF)?; +// self.db.put(k, v, &default_cf, None)?; +// +// Ok(()) +// } +// #[allow(unused_variables)] +// pub fn create_table(&self, name: &str, _global: bool) -> Result<()> { +// match self.db.create_column_family(table_name_to_cf_name(name)) { +// Ok(_) => Ok(()), +// Err(s) if s.bridge_code == StatusBridgeCode::EXISTING_ERROR => Ok(()), +// Err(e) => Err(CozoError::Storage(e)) +// } +// } +// #[allow(unused_variables)] +// pub fn drop_table(&self, name: &str, _global: bool) -> Result<()> { +// self.db.drop_column_family(table_name_to_cf_name(name))?; +// Ok(()) +// } +// +// pub fn get_next_local_id(&self, global: bool) -> usize { +// if global { +// 0 +// } else { +// self.last_local_id.fetch_add(1, Ordering::Relaxed) + 1 +// } +// } +// } +// +// #[inline] +// fn table_name_to_cf_name(name: &str) -> String { +// format!("${}", name) +// } +// +// pub trait Storage {} +// +// pub struct DummyStorage; +// +// impl Storage for DummyStorage {} +// +// impl Storage for RocksStorage {} +// +// #[cfg(test)] +// mod tests { +// use std::str::from_utf8; +// use crate::value::{ByteArrayBuilder, cozo_comparator_v1, Value}; +// +// // #[test] +// // fn import() { +// // use cozo_rocks::*; +// // let options = Options::default() +// // .increase_parallelism() +// // .optimize_level_style_compaction() +// // .set_create_if_missing(true) +// // .set_comparator("cozo_comparator_v1", cozo_comparator_v1); +// // +// // let db = DB::open(options, +// // "xxyyzz.db".as_ref()).unwrap(); +// // +// // let mut builder = ByteArrayBuilder::default(); +// // builder.build_value(&Value::RefString("A key")); +// // let key = builder; +// // +// // let mut builder = ByteArrayBuilder::default(); +// // builder.build_value(&Value::RefString("Another key")); +// // let key2 = builder; +// // let cf = db.get_cf_handle("default").unwrap(); +// // println!("{:?}", db.all_cf_names()); +// // +// // let val = db.get(&key, &cf, None).unwrap(); +// // println!("before anything {}", val.is_none()); +// // +// // db.put(&key, "A motherfucking value!!! 👋👋👋", &cf, None).unwrap(); +// // let batch = WriteBatch::default(); +// // batch.put(&key2, "Another motherfucking value!!! 👋👋👋", &cf).unwrap(); +// // db.write(batch, None).unwrap(); +// // // db.put("Yes man", "A motherfucking value!!! 👋👋👋", None).unwrap(); +// // let val = db.get(&key, &cf, None).unwrap().unwrap(); +// // println!("1 {}", from_utf8(val.as_ref()).unwrap()); +// // let val = db.get(&key2, &cf, None).unwrap().unwrap(); +// // // let val = val.as_bytes(); +// // println!("2 {}", from_utf8(val.as_ref()).unwrap()); +// // let val = db.get(&key, &cf, None).unwrap().unwrap(); +// // println!("3 {}", from_utf8(val.as_ref()).unwrap()); +// // println!("4 {}", from_utf8(db.get(&key, &cf, None).unwrap().unwrap().as_ref()).unwrap()); +// // } +// } \ No newline at end of file diff --git a/src/typing.rs b/src/typing.rs index 3771bcf5..0a9d6432 100644 --- a/src/typing.rs +++ b/src/typing.rs @@ -1,256 +1,256 @@ -use std::collections::BTreeMap; -use std::fmt::{Debug, Display, Formatter, Write}; -use crate::env::{Env, Environment}; -use crate::value::{StaticValue, Value}; - -#[derive(Debug, Eq, PartialEq, Clone)] -pub enum BaseType { - Bool, - Int, - UInt, - Float, - String, - BitArr, - U8Arr, - I8Arr, - I16Arr, - U16Arr, - I32Arr, - U32Arr, - I64Arr, - U64Arr, - F16Arr, - F32Arr, - F64Arr, - C32Arr, - C64Arr, - C128Arr, - Uuid, - Timestamp, - Datetime, - Timezone, - Date, - Time, - Duration, - BigInt, - BigDecimal, - Inet, - Crs, -} - - -#[derive(Debug, PartialEq, Clone)] -pub struct Col { - pub name: String, - pub typ: Typing, - pub default: StaticValue, -} - - -#[derive(Debug, PartialEq, Eq, Ord, PartialOrd, Clone)] -pub enum StorageStatus { - Planned, - Verified, - Stored, -} - -#[derive(PartialEq, Eq, Ord, PartialOrd, Clone)] -pub struct TableId { - pub name: String, - pub local_id: usize, -} - -impl TableId { - pub fn is_global(&self) -> bool { - self.local_id == 0 - } -} - - -impl Debug for TableId { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - f.write_str(&self.name)?; - if self.local_id > 0 { - f.write_str(&format!("({})", self.local_id))?; - } - Ok(()) - } -} - -#[derive(Ord, PartialOrd, Eq, PartialEq, Clone)] -pub struct ColumnId { - table_id: TableId, - is_key: bool, - col_order: usize, -} - -impl Debug for ColumnId { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - f.write_str(&format!("{:?}", self.table_id))?; - if self.is_key { - f.write_char('*')?; - } else { - f.write_char('-')?; - } - f.write_str(&format!("{}", self.col_order))?; - Ok(()) - } -} - -#[derive(Debug, PartialEq, Clone)] -pub struct Node { - pub status: StorageStatus, - pub id: TableId, - pub keys: Vec, - pub cols: Vec, - pub out_e: Vec, - pub in_e: Vec, - pub attached: Vec, - pub col_map: BTreeMap, -} - -#[derive(Debug, PartialEq, Clone)] -pub struct Edge { - pub status: StorageStatus, - pub src: TableId, - pub dst: TableId, - pub id: TableId, - pub keys: Vec, - pub cols: Vec, - pub col_map: BTreeMap, -} - -#[derive(Debug, PartialEq, Clone)] -pub struct Columns { - pub status: StorageStatus, - pub attached: TableId, - pub id: TableId, - pub cols: Vec, -} - -#[derive(Debug, PartialEq, Clone)] -pub struct Index { - pub status: StorageStatus, - pub id: TableId, - pub attached: TableId, - pub cols: Vec, -} - - -#[derive(Eq, PartialEq, Clone)] -pub enum Typing { - Any, - Base(BaseType), - HList(Box), - Nullable(Box), - Tuple(Vec), - NamedTuple(BTreeMap), -} - -impl Display for Typing { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - match self { - Typing::Any => f.write_str("Any")?, - Typing::Base(b) => { - match b { - BaseType::Bool => f.write_str("Bool")?, - BaseType::Int => f.write_str("Int")?, - BaseType::UInt => f.write_str("UInt")?, - BaseType::Float => f.write_str("Float")?, - BaseType::String => f.write_str("String")?, - BaseType::BitArr => f.write_str("BitArr")?, - BaseType::U8Arr => f.write_str("U8Arr")?, - BaseType::I8Arr => f.write_str("I8Arr")?, - BaseType::I16Arr => f.write_str("I16Arr")?, - BaseType::U16Arr => f.write_str("U16Arr")?, - BaseType::I32Arr => f.write_str("I32Arr")?, - BaseType::U32Arr => f.write_str("U32Arr")?, - BaseType::I64Arr => f.write_str("I64Arr")?, - BaseType::U64Arr => f.write_str("U64Arr")?, - BaseType::F16Arr => f.write_str("F16Arr")?, - BaseType::F32Arr => f.write_str("F32Arr")?, - BaseType::F64Arr => f.write_str("F64Arr")?, - BaseType::C32Arr => f.write_str("C32Arr")?, - BaseType::C64Arr => f.write_str("C64Arr")?, - BaseType::C128Arr => f.write_str("C128Arr")?, - BaseType::Uuid => f.write_str("Uuid")?, - BaseType::Timestamp => f.write_str("Timestamp")?, - BaseType::Datetime => f.write_str("Datetime")?, - BaseType::Timezone => f.write_str("Timezone")?, - BaseType::Date => f.write_str("Date")?, - BaseType::Time => f.write_str("Time")?, - BaseType::Duration => f.write_str("Duration")?, - BaseType::BigInt => f.write_str("BigInt")?, - BaseType::BigDecimal => f.write_str("BigDecimal")?, - BaseType::Inet => f.write_str("Inet")?, - BaseType::Crs => f.write_str("Crs")? - } - } - Typing::HList(l) => { - f.write_char('[')?; - Display::fmt(l, f)?; - f.write_char(']')?; - } - Typing::Nullable(d) => { - f.write_char('?')?; - Display::fmt(d, f)?; - } - Typing::Tuple(_) => todo!(), - Typing::NamedTuple(_) => todo!() - } - Ok(()) - } -} - -impl Debug for Typing { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - Display::fmt(self, f) - } -} - -#[derive(Debug, PartialEq, Clone)] -pub enum Structured { - Typing(Typing), - Node(Node), - Edge(Edge), - Columns(Columns), - Index(Index), - Value(StaticValue), -} - -impl Structured { - pub fn storage_id(&self) -> Option { - match self { - Structured::Typing(_) => None, - Structured::Node(n) => Some(n.id.clone()), - Structured::Edge(e) => Some(e.id.clone()), - Structured::Columns(c) => Some(c.id.clone()), - Structured::Index(i) => Some(i.id.clone()), - Structured::Value(_) => None - } - } -} - -impl Environment { - pub fn define_base_types(&mut self) { - self.define("Any".to_string(), Structured::Typing(Typing::Any)); - self.define("Bool".to_string(), Structured::Typing(Typing::Base(BaseType::Bool))); - self.define("Int".to_string(), Structured::Typing(Typing::Base(BaseType::Int))); - self.define("UInt".to_string(), Structured::Typing(Typing::Base(BaseType::UInt))); - self.define("Float".to_string(), Structured::Typing(Typing::Base(BaseType::Float))); - self.define("String".to_string(), Structured::Typing(Typing::Base(BaseType::String))); - self.define("Bytes".to_string(), Structured::Typing(Typing::Base(BaseType::U8Arr))); - self.define("U8Arr".to_string(), Structured::Typing(Typing::Base(BaseType::U8Arr))); - self.define("Uuid".to_string(), Structured::Typing(Typing::Base(BaseType::Uuid))); - self.define("Timestamp".to_string(), Structured::Typing(Typing::Base(BaseType::Timestamp))); - self.define("Datetime".to_string(), Structured::Typing(Typing::Base(BaseType::Datetime))); - self.define("Timezone".to_string(), Structured::Typing(Typing::Base(BaseType::Timezone))); - self.define("Date".to_string(), Structured::Typing(Typing::Base(BaseType::Date))); - self.define("Time".to_string(), Structured::Typing(Typing::Base(BaseType::Time))); - self.define("Duration".to_string(), Structured::Typing(Typing::Base(BaseType::Duration))); - self.define("BigInt".to_string(), Structured::Typing(Typing::Base(BaseType::BigInt))); - self.define("BigDecimal".to_string(), Structured::Typing(Typing::Base(BaseType::BigDecimal))); - self.define("Int".to_string(), Structured::Typing(Typing::Base(BaseType::Int))); - self.define("Crs".to_string(), Structured::Typing(Typing::Base(BaseType::Crs))); - } -} \ No newline at end of file +// use std::collections::BTreeMap; +// use std::fmt::{Debug, Display, Formatter, Write}; +// use crate::env::{Env, Environment}; +// use crate::value::{StaticValue, Value}; +// +// #[derive(Debug, Eq, PartialEq, Clone)] +// pub enum BaseType { +// Bool, +// Int, +// UInt, +// Float, +// String, +// BitArr, +// U8Arr, +// I8Arr, +// I16Arr, +// U16Arr, +// I32Arr, +// U32Arr, +// I64Arr, +// U64Arr, +// F16Arr, +// F32Arr, +// F64Arr, +// C32Arr, +// C64Arr, +// C128Arr, +// Uuid, +// Timestamp, +// Datetime, +// Timezone, +// Date, +// Time, +// Duration, +// BigInt, +// BigDecimal, +// Inet, +// Crs, +// } +// +// +// #[derive(Debug, PartialEq, Clone)] +// pub struct Col { +// pub name: String, +// pub typ: Typing, +// pub default: StaticValue, +// } +// +// +// #[derive(Debug, PartialEq, Eq, Ord, PartialOrd, Clone)] +// pub enum StorageStatus { +// Planned, +// Verified, +// Stored, +// } +// +// #[derive(PartialEq, Eq, Ord, PartialOrd, Clone)] +// pub struct TableId { +// pub name: String, +// pub local_id: usize, +// } +// +// impl TableId { +// pub fn is_global(&self) -> bool { +// self.local_id == 0 +// } +// } +// +// +// impl Debug for TableId { +// fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { +// f.write_str(&self.name)?; +// if self.local_id > 0 { +// f.write_str(&format!("({})", self.local_id))?; +// } +// Ok(()) +// } +// } +// +// #[derive(Ord, PartialOrd, Eq, PartialEq, Clone)] +// pub struct ColumnId { +// table_id: TableId, +// is_key: bool, +// col_order: usize, +// } +// +// impl Debug for ColumnId { +// fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { +// f.write_str(&format!("{:?}", self.table_id))?; +// if self.is_key { +// f.write_char('*')?; +// } else { +// f.write_char('-')?; +// } +// f.write_str(&format!("{}", self.col_order))?; +// Ok(()) +// } +// } +// +// #[derive(Debug, PartialEq, Clone)] +// pub struct Node { +// pub status: StorageStatus, +// pub id: TableId, +// pub keys: Vec, +// pub cols: Vec, +// pub out_e: Vec, +// pub in_e: Vec, +// pub attached: Vec, +// pub col_map: BTreeMap, +// } +// +// #[derive(Debug, PartialEq, Clone)] +// pub struct Edge { +// pub status: StorageStatus, +// pub src: TableId, +// pub dst: TableId, +// pub id: TableId, +// pub keys: Vec, +// pub cols: Vec, +// pub col_map: BTreeMap, +// } +// +// #[derive(Debug, PartialEq, Clone)] +// pub struct Columns { +// pub status: StorageStatus, +// pub attached: TableId, +// pub id: TableId, +// pub cols: Vec, +// } +// +// #[derive(Debug, PartialEq, Clone)] +// pub struct Index { +// pub status: StorageStatus, +// pub id: TableId, +// pub attached: TableId, +// pub cols: Vec, +// } +// +// +// #[derive(Eq, PartialEq, Clone)] +// pub enum Typing { +// Any, +// Base(BaseType), +// HList(Box), +// Nullable(Box), +// Tuple(Vec), +// NamedTuple(BTreeMap), +// } +// +// impl Display for Typing { +// fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { +// match self { +// Typing::Any => f.write_str("Any")?, +// Typing::Base(b) => { +// match b { +// BaseType::Bool => f.write_str("Bool")?, +// BaseType::Int => f.write_str("Int")?, +// BaseType::UInt => f.write_str("UInt")?, +// BaseType::Float => f.write_str("Float")?, +// BaseType::String => f.write_str("String")?, +// BaseType::BitArr => f.write_str("BitArr")?, +// BaseType::U8Arr => f.write_str("U8Arr")?, +// BaseType::I8Arr => f.write_str("I8Arr")?, +// BaseType::I16Arr => f.write_str("I16Arr")?, +// BaseType::U16Arr => f.write_str("U16Arr")?, +// BaseType::I32Arr => f.write_str("I32Arr")?, +// BaseType::U32Arr => f.write_str("U32Arr")?, +// BaseType::I64Arr => f.write_str("I64Arr")?, +// BaseType::U64Arr => f.write_str("U64Arr")?, +// BaseType::F16Arr => f.write_str("F16Arr")?, +// BaseType::F32Arr => f.write_str("F32Arr")?, +// BaseType::F64Arr => f.write_str("F64Arr")?, +// BaseType::C32Arr => f.write_str("C32Arr")?, +// BaseType::C64Arr => f.write_str("C64Arr")?, +// BaseType::C128Arr => f.write_str("C128Arr")?, +// BaseType::Uuid => f.write_str("Uuid")?, +// BaseType::Timestamp => f.write_str("Timestamp")?, +// BaseType::Datetime => f.write_str("Datetime")?, +// BaseType::Timezone => f.write_str("Timezone")?, +// BaseType::Date => f.write_str("Date")?, +// BaseType::Time => f.write_str("Time")?, +// BaseType::Duration => f.write_str("Duration")?, +// BaseType::BigInt => f.write_str("BigInt")?, +// BaseType::BigDecimal => f.write_str("BigDecimal")?, +// BaseType::Inet => f.write_str("Inet")?, +// BaseType::Crs => f.write_str("Crs")? +// } +// } +// Typing::HList(l) => { +// f.write_char('[')?; +// Display::fmt(l, f)?; +// f.write_char(']')?; +// } +// Typing::Nullable(d) => { +// f.write_char('?')?; +// Display::fmt(d, f)?; +// } +// Typing::Tuple(_) => todo!(), +// Typing::NamedTuple(_) => todo!() +// } +// Ok(()) +// } +// } +// +// impl Debug for Typing { +// fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { +// Display::fmt(self, f) +// } +// } +// +// #[derive(Debug, PartialEq, Clone)] +// pub enum Structured { +// Typing(Typing), +// Node(Node), +// Edge(Edge), +// Columns(Columns), +// Index(Index), +// Value(StaticValue), +// } +// +// impl Structured { +// pub fn storage_id(&self) -> Option { +// match self { +// Structured::Typing(_) => None, +// Structured::Node(n) => Some(n.id.clone()), +// Structured::Edge(e) => Some(e.id.clone()), +// Structured::Columns(c) => Some(c.id.clone()), +// Structured::Index(i) => Some(i.id.clone()), +// Structured::Value(_) => None +// } +// } +// } +// +// impl Environment { +// pub fn define_base_types(&mut self) { +// self.define("Any".to_string(), Structured::Typing(Typing::Any)); +// self.define("Bool".to_string(), Structured::Typing(Typing::Base(BaseType::Bool))); +// self.define("Int".to_string(), Structured::Typing(Typing::Base(BaseType::Int))); +// self.define("UInt".to_string(), Structured::Typing(Typing::Base(BaseType::UInt))); +// self.define("Float".to_string(), Structured::Typing(Typing::Base(BaseType::Float))); +// self.define("String".to_string(), Structured::Typing(Typing::Base(BaseType::String))); +// self.define("Bytes".to_string(), Structured::Typing(Typing::Base(BaseType::U8Arr))); +// self.define("U8Arr".to_string(), Structured::Typing(Typing::Base(BaseType::U8Arr))); +// self.define("Uuid".to_string(), Structured::Typing(Typing::Base(BaseType::Uuid))); +// self.define("Timestamp".to_string(), Structured::Typing(Typing::Base(BaseType::Timestamp))); +// self.define("Datetime".to_string(), Structured::Typing(Typing::Base(BaseType::Datetime))); +// self.define("Timezone".to_string(), Structured::Typing(Typing::Base(BaseType::Timezone))); +// self.define("Date".to_string(), Structured::Typing(Typing::Base(BaseType::Date))); +// self.define("Time".to_string(), Structured::Typing(Typing::Base(BaseType::Time))); +// self.define("Duration".to_string(), Structured::Typing(Typing::Base(BaseType::Duration))); +// self.define("BigInt".to_string(), Structured::Typing(Typing::Base(BaseType::BigInt))); +// self.define("BigDecimal".to_string(), Structured::Typing(Typing::Base(BaseType::BigDecimal))); +// self.define("Int".to_string(), Structured::Typing(Typing::Base(BaseType::Int))); +// self.define("Crs".to_string(), Structured::Typing(Typing::Base(BaseType::Crs))); +// } +// } \ No newline at end of file diff --git a/src/value.rs b/src/value.rs index b8731cd7..81fa693c 100644 --- a/src/value.rs +++ b/src/value.rs @@ -1,644 +1,637 @@ -use std::borrow::{Cow}; -use std::cmp::{min, Ordering}; -use std::collections::{BTreeMap}; -use std::io::{Write}; -use ordered_float::OrderedFloat; -use uuid::Uuid; -use crate::typing::{Typing}; -use Ordering::{Greater, Less, Equal}; -use std::sync::Arc; - -// TODO: array types, alignment of values -#[repr(u8)] -#[derive(Ord, PartialOrd, Eq, PartialEq)] -pub enum ValueTag { - BoolFalseTag = 0, - NullTag = 2, - BoolTrueTag = 4, - FwdEdgeTag = 6, - BwdEdgeTag = 8, - IntTag = 11, - FloatTag = 13, - StringTag = 15, - UuidTag = 17, - UIntTag = 21, - // TimestampTag = 23, - // DatetimeTag = 25, - // TimezoneTag = 27, - // DateTag = 27, - // TimeTag = 29, - // DurationTag = 31, - // BigIntTag = 51, - // BigDecimalTag = 53, - // InetTag = 55, - // CrsTag = 57, - // BitArrTag = 60, - // U8ArrTag = 61, - // I8ArrTag = 62, - // U16ArrTag = 63, - // I16ArrTag = 64, - // U32ArrTag = 65, - // I32ArrTag = 66, - // U64ArrTag = 67, - // I64ArrTag = 68, - // F16ArrTag = 69, - // F32ArrTag = 70, - // F64ArrTag = 71, - // C32ArrTag = 72, - // C64ArrTag = 73, - // C128ArrTag = 74, - ListTag = 101, - DictTag = 103, -} - -#[derive(Copy, Clone, Debug, PartialEq, Eq)] -pub enum EdgeDirKind { - FwdEdgeDir, - BwdEdgeDir, -} - -#[derive(Debug, Clone)] -pub enum Value<'a> { - Null, - Bool(bool), - EdgeDir(EdgeDirKind), - UInt(u64), - Int(i64), - Float(f64), - Uuid(Uuid), - RefString(&'a str), - OwnString(Arc), - List(Arc>>), - Dict(Arc, Value<'a>>>), -} - -pub type StaticValue = Value<'static>; - -impl<'a> Value<'a> { - pub fn get_list(&self) -> Option>> { - match self { - Value::List(v) => Some(v.clone()), - _ => None - } - } - pub fn get_string(&self) -> Option> { - match self { - Value::OwnString(v) => Some(v.clone()), - Value::RefString(v) => Some(Arc::new(v.to_string())), - _ => None - } - } -} - -impl<'a> PartialEq for Value<'a> { - fn eq(&self, other: &Self) -> bool { - use Value::*; - - match (self, other) { - (Null, Null) => true, - (Bool(a), Bool(b)) => a == b, - (EdgeDir(a), EdgeDir(b)) => a == b, - (UInt(a), UInt(b)) => a == b, - (Int(a), Int(b)) => a == b, - (Float(a), Float(b)) => a == b, - (Uuid(a), Uuid(b)) => a == b, - (RefString(a), RefString(b)) => a == b, - (RefString(a), OwnString(b)) => *a == **b, - (OwnString(a), RefString(b)) => **a == *b, - (OwnString(a), OwnString(b)) => a == b, - (List(a), List(b)) => a == b, - (Dict(a), Dict(b)) => a == b, - _ => false - } - } -} - -pub struct ByteArrayParser<'a> { - bytes: &'a [u8], - current: usize, -} - -impl<'a> ByteArrayParser<'a> { - pub fn new>(source: &'a T) -> Self { - Self { bytes: source.as_ref(), current: 0 } - } - - #[inline] - 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]) - } - } - - #[inline] - fn at_end(&self) -> bool { - self.current == self.bytes.len() - } - - #[inline] - 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) - } - - #[inline] - pub fn parse_value_tag(&mut self) -> Option { - use ValueTag::*; - - let u = self.parse_varint()?; - match u { - u if u == NullTag as u64 => Some(NullTag), - u if u == BoolTrueTag as u64 => Some(BoolTrueTag), - u if u == BoolFalseTag as u64 => Some(BoolFalseTag), - u if u == FwdEdgeTag as u64 => Some(FwdEdgeTag), - u if u == BwdEdgeTag as u64 => Some(BwdEdgeTag), - u if u == IntTag as u64 => Some(IntTag), - u if u == FloatTag as u64 => Some(FloatTag), - u if u == StringTag as u64 => Some(StringTag), - u if u == UIntTag as u64 => Some(UIntTag), - u if u == ListTag as u64 => Some(ListTag), - u if u == DictTag as u64 => Some(DictTag), - u if u == UuidTag as u64 => Some(UuidTag), - _ => None - } - } - - #[inline] - pub fn compare_varint(&mut self, other: &mut Self) -> Ordering { - self.parse_varint().expect( - "Failed to parse VarInt when comparing" - ).cmp(&other.parse_varint().expect( - "Failed to parse VarInt when comparing" - )) - } - - #[inline] - 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 - }) - } - - #[inline] - pub fn compare_zigzag(&mut self, other: &mut Self) -> Ordering { - self.parse_zigzag().expect( - "Failed to parse ZigZag when comparing" - ).cmp(&other.parse_zigzag().expect( - "Failed to parse ZigZag when comparing" - )) - } - - #[inline] - pub fn parse_float(&mut self) -> Option { - let buf = self.advance(8)?.try_into().ok()?; - Some(f64::from_be_bytes(buf)) - } - - #[inline] - pub fn parse_uuid(&mut self) -> Option { - Uuid::from_slice(self.advance(16)?).ok() - } - - #[inline] - pub fn compare_float(&mut self, other: &mut Self) -> Ordering { - OrderedFloat(self.parse_float().expect( - "Failed to parse Float when comparing" - )).cmp(&OrderedFloat(other.parse_float().expect( - "Failed to parse Float when comparing" - ))) - } - // This should first compare UUID version, then for V1, compare the timestamps - #[inline] - pub fn compare_uuid(&mut self, other: &mut Self) -> Ordering { - let ua = self.parse_uuid().expect( - "Failed to parse Uuid when comparing" - ); - let (a3, a2, a1, a4) = ua.as_fields(); - let ub = other.parse_uuid().expect( - "Failed to parse Uuid when comparing" - ); - let (b3, b2, b1, b4) = ub.as_fields(); - if let x @ (Greater | Less) = a1.cmp(&b1) { return x; } - if let x @ (Greater | Less) = a2.cmp(&b2) { return x; } - if let x @ (Greater | Less) = a3.cmp(&b3) { return x; } - a4.cmp(b4) - } - - #[inline] - 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)) - // } - std::str::from_utf8(bytes).ok() - } - - #[inline] - pub fn compare_string(&mut self, other: &mut Self) -> Ordering { - let len_a = self.parse_varint().expect("Failed to get String length when comparing"); - let len_b = other.parse_varint().expect("Failed to get String length when comparing"); - for _ in 0..min(len_a, len_b) { - let byte_a = self.advance(1).expect("Unexpected end of String when comparing")[0]; - let byte_b = other.advance(1).expect("Unexpected end of String when comparing")[0]; - if let x @ (Greater | Less) = byte_a.cmp(&byte_b) { return x; } - } - 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> { - use ValueTag::*; - use Value::*; - use EdgeDirKind::*; - - match self.parse_value_tag()? { - NullTag => Some(Null), - BoolTrueTag => Some(Bool(true)), - BoolFalseTag => Some(Bool(false)), - FwdEdgeTag => Some(EdgeDir(FwdEdgeDir)), - BwdEdgeTag => Some(EdgeDir(BwdEdgeDir)), - IntTag => Some(Int(self.parse_zigzag()?)), - FloatTag => Some(Float(self.parse_float()?)), - StringTag => Some(RefString(self.parse_string()?)), - UIntTag => Some(UInt(self.parse_varint()?)), - ListTag => Some(List(Arc::new(self.parse_list()?))), - DictTag => Some(Dict(Arc::new(self.parse_dict()?))), - UuidTag => Some(Uuid(self.parse_uuid()?)) - } - } - pub fn compare_value(&mut self, other: &mut Self) -> Ordering { - use ValueTag::*; - - match (self.parse_value_tag(), other.parse_value_tag()) { - (None, None) => Equal, - (None, Some(_)) => Less, - (Some(_), None) => Greater, - (Some(type_a), Some(type_b)) => { - if let x @ (Greater | Less) = type_a.cmp(&type_b) { return x; } - match type_a { - IntTag => self.compare_zigzag(other), - FloatTag => self.compare_float(other), - StringTag => self.compare_string(other), - UIntTag => self.compare_varint(other), - ListTag => self.compare_list(other), - DictTag => self.compare_dict(other), - UuidTag => self.compare_uuid(other), - NullTag | BoolTrueTag | BoolFalseTag | FwdEdgeTag | BwdEdgeTag => Equal - } - } - } - } - pub fn compare_list(&mut self, other: &mut Self) -> Ordering { - let len_a = self.parse_varint().expect("Failed to get List length when comparing"); - let len_b = other.parse_varint().expect("Failed to get List length when comparing"); - for _ in 0..min(len_a, len_b) { - if let x @ (Greater | Less) = self.compare_value(other) { return x; } - } - len_a.cmp(&len_b) - } - pub fn parse_dict(&mut self) -> Option, Value<'a>>> { - let l = self.parse_varint()?; - let mut ret = BTreeMap::new(); - - 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().expect("Failed to get Dict length when comparing"); - let len_b = other.parse_varint().expect("Failed to get Dict length when comparing"); - for _ in 0..min(len_a, len_b) { - if let x @ (Greater | Less) = self.compare_string(other) { return x; } - if let x @ (Greater | Less) = self.compare_value(other) { return x; } - } - len_a.cmp(&len_b) - } -} - -pub struct ByteArrayBuilder> { - byte_writer: T, -} - -impl> AsRef<[u8]> for ByteArrayBuilder { - fn as_ref(&self) -> &[u8] { - self.byte_writer.as_ref() - } -} - -impl ByteArrayBuilder> { - pub fn default() -> Self { Self { byte_writer: vec![] } } - pub fn with_capacity(size: usize) -> Self { - Self::new(Vec::with_capacity(size)) - } -} - -impl> ByteArrayBuilder { - pub fn get(self) -> T { - self.byte_writer - } - - pub fn new(byte_writer: T) -> Self { - Self { byte_writer } - } - - #[inline] - pub fn build_varint(&mut self, u: u64) -> &mut Self { - let mut u = u; - while u > 0b01111111 { - self.byte_writer.write_all(&[0b10000000 | (u as u8 & 0b01111111)]).expect( - "Failed to write when building VarInt" - ); - u >>= 7; - } - self.byte_writer.write_all(&[u as u8]).expect( - "Failed to write when building Varint" - ); - self - } - - #[inline] - pub fn build_zigzag(&mut self, i: i64) -> &mut Self { - 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); - self - } - - #[inline] - pub fn build_float(&mut self, f: f64) -> &mut Self { - self.byte_writer.write_all(&f.to_be_bytes()).expect( - "Failed to write when building Float" - ); - self - } - - #[inline] - pub fn build_uuid(&mut self, u: Uuid) -> &mut Self { - self.byte_writer.write_all(u.as_bytes()).expect( - "Failed to write when building Uuid" - ); - self - } - - #[inline] - pub fn build_string(&mut self, s: &str) -> &mut Self { - self.build_varint(s.len() as u64); - self.byte_writer.write_all(s.as_bytes()).expect("Failed to write when building String"); - self - } - - #[inline] - pub fn build_tag(&mut self, t: ValueTag) -> &mut Self { - self.byte_writer.write_all(&[t as u8]).expect("Failed to write when building Tag"); - self - } - - pub fn build_value(&mut self, v: &Value) -> &mut Self { - use ValueTag::*; - - match v { - Value::Null => self.build_tag(NullTag), - Value::Bool(b) => self.build_tag(if *b { BoolTrueTag } else { BoolFalseTag }), - Value::EdgeDir(e) => self.build_tag(match e { - EdgeDirKind::FwdEdgeDir => { FwdEdgeTag } - EdgeDirKind::BwdEdgeDir => { BwdEdgeTag } - }), - Value::UInt(u) => { - self.build_tag(UIntTag).build_varint(*u) - } - Value::Int(i) => { - self.build_tag(IntTag).build_zigzag(*i) - } - Value::Float(f) => { - self.build_tag(FloatTag).build_float(*f) - } - Value::OwnString(s) => { - self.build_tag(StringTag).build_string(s) - } - Value::RefString(s) => { - self.build_tag(StringTag).build_string(s) - } - Value::List(l) => { - self.build_tag(ListTag).build_list(l) - } - Value::Dict(d) => { - self.build_tag(DictTag).build_dict(d) - } - Value::Uuid(u) => { - self.build_tag(UuidTag).build_uuid(*u) - } - } - } - - pub fn build_list(&mut self, l: &[Value]) -> &mut Self { - self.build_varint(l.len() as u64); - for el in l { - self.build_value(el); - } - self - } - - pub fn build_dict(&mut self, d: &BTreeMap, Value>) -> &mut Self { - self.build_varint(d.len() as u64); - for (k, v) in d { - self.build_string(k).build_value(v); - } - self - } -} - - -pub fn cozo_comparator_v1(a: &[u8], b: &[u8]) -> i8 { - let mut ba = &mut ByteArrayParser { bytes: a, current: 0 }; - let mut bb = &mut ByteArrayParser { bytes: b, current: 0 }; - match ba.compare_varint(&mut bb) { - Less => return -1, - Greater => return 1, - Equal => {} - } - match cmp_data(&mut ba, &mut bb) { - Less => -1, - Equal => 0, - Greater => 1 - } -} - -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 Equal, - (true, false) => return Less, - (false, true) => return Greater, - (false, false) => () - } - if let x @ (Greater | Less) = pa.compare_value(pb) { return x; } - } -} - - -impl<'a> Value<'a> { - pub fn owned_clone(&self) -> StaticValue { - use Value::*; - - match self { - Null => Null, - Bool(b) => Bool(*b), - EdgeDir(dir) => EdgeDir(*dir), - UInt(u) => UInt(*u), - Int(i) => Int(*i), - Float(f) => Float(*f), - RefString(s) => OwnString(Arc::new(s.to_string())), - OwnString(s) => OwnString(s.clone()), - List(l) => { - let mut inner = Vec::with_capacity(l.len()); - - for el in l.iter() { - inner.push(el.owned_clone()) - } - List(Arc::new(inner)) - } - Dict(d) => { - let mut inner = BTreeMap::new(); - for (k, v) in d.iter() { - let new_k = Cow::from(k.clone().into_owned()); - inner.insert(new_k, v.owned_clone()); - } - Dict(Arc::new(inner)) - } - Uuid(u) => Uuid(*u), - } - } -} - -#[derive(Clone, Debug)] -pub struct CoercionError<'a> { - pub msg: String, - pub val: Value<'a>, -} - -impl Typing { - pub fn coerce<'a>(&self, v: Value<'a>) -> Result, CoercionError<'a>> { - // TODO - Ok(v) - } -} - -pub struct CozoKey<'a> { - pub table_id: i64, - 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 builder = ByteArrayBuilder::default(); - builder.build_zigzag(i); - let mut parser = ByteArrayParser::new(&builder); - 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); - } - - - #[test] - fn size() { - println!("{:?}", std::mem::size_of::()); - println!("{:?}", std::mem::size_of::()); - println!("{:?}", std::mem::size_of::()); - println!("{:?}", std::mem::size_of::, Value>>()); - println!("{:?}", std::mem::size_of::>()); - println!("{:?}", std::mem::size_of::>()); - println!("{:?}", std::mem::size_of::>>()); - println!("{:?}", std::mem::size_of::>>()); - println!("{:?}", std::mem::size_of::()); - println!("{:?}", std::mem::size_of::<&str>()); - } -} +// use std::borrow::{Cow}; +// use std::cmp::{min, Ordering}; +// use std::collections::{BTreeMap}; +// use std::io::{Write}; +// use ordered_float::OrderedFloat; +// use uuid::Uuid; +// use crate::typing::{Typing}; +// use Ordering::{Greater, Less, Equal}; +// use std::sync::Arc; +// +// // TODO: array types, alignment of values +// #[repr(u8)] +// #[derive(Ord, PartialOrd, Eq, PartialEq)] +// pub enum ValueTag { +// BoolFalseTag = 0, +// NullTag = 2, +// BoolTrueTag = 4, +// FwdEdgeTag = 6, +// BwdEdgeTag = 8, +// IntTag = 11, +// FloatTag = 13, +// StringTag = 15, +// UuidTag = 17, +// UIntTag = 21, +// // TimestampTag = 23, +// // DatetimeTag = 25, +// // TimezoneTag = 27, +// // DateTag = 27, +// // TimeTag = 29, +// // DurationTag = 31, +// // BigIntTag = 51, +// // BigDecimalTag = 53, +// // InetTag = 55, +// // CrsTag = 57, +// // BitArrTag = 60, +// // U8ArrTag = 61, +// // I8ArrTag = 62, +// // U16ArrTag = 63, +// // I16ArrTag = 64, +// // U32ArrTag = 65, +// // I32ArrTag = 66, +// // U64ArrTag = 67, +// // I64ArrTag = 68, +// // F16ArrTag = 69, +// // F32ArrTag = 70, +// // F64ArrTag = 71, +// // C32ArrTag = 72, +// // C64ArrTag = 73, +// // C128ArrTag = 74, +// ListTag = 101, +// DictTag = 103, +// } +// +// #[derive(Copy, Clone, Debug, PartialEq, Eq)] +// pub enum EdgeDirKind { +// FwdEdgeDir, +// BwdEdgeDir, +// } +// +// #[derive(Debug, Clone)] +// pub enum Value<'a> { +// Null, +// Bool(bool), +// EdgeDir(EdgeDirKind), +// UInt(u64), +// Int(i64), +// Float(f64), +// Uuid(Uuid), +// Text(Arc>), +// List(Arc>>), +// Dict(Arc, Value<'a>>>), +// } +// +// pub type StaticValue = Value<'static>; +// +// impl<'a> Value<'a> { +// pub fn get_list(&self) -> Option>> { +// match self { +// Value::List(v) => Some(v.clone()), +// _ => None +// } +// } +// pub fn get_string(&self) -> Option> { +// match self { +// Value::Text(v) => todo!(), +// // Value::Text(v) => Some(Arc::new(v.clone().into_owned())), +// _ => None +// } +// } +// } +// +// impl<'a> PartialEq for Value<'a> { +// fn eq(&self, other: &Self) -> bool { +// use Value::*; +// +// match (self, other) { +// (Null, Null) => true, +// (Bool(a), Bool(b)) => a == b, +// (EdgeDir(a), EdgeDir(b)) => a == b, +// (UInt(a), UInt(b)) => a == b, +// (Int(a), Int(b)) => a == b, +// (Float(a), Float(b)) => a == b, +// (Uuid(a), Uuid(b)) => a == b, +// (Text(a), Text(b)) => a == b, +// (List(a), List(b)) => a == b, +// (Dict(a), Dict(b)) => a == b, +// _ => false +// } +// } +// } +// +// pub struct ByteArrayParser<'a> { +// bytes: &'a [u8], +// current: usize, +// } +// +// impl<'a> ByteArrayParser<'a> { +// pub fn new>(source: &'a T) -> Self { +// Self { bytes: source.as_ref(), current: 0 } +// } +// +// #[inline] +// 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]) +// } +// } +// +// #[inline] +// fn at_end(&self) -> bool { +// self.current == self.bytes.len() +// } +// +// #[inline] +// 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) +// } +// +// #[inline] +// pub fn parse_value_tag(&mut self) -> Option { +// use ValueTag::*; +// +// let u = self.parse_varint()?; +// match u { +// u if u == NullTag as u64 => Some(NullTag), +// u if u == BoolTrueTag as u64 => Some(BoolTrueTag), +// u if u == BoolFalseTag as u64 => Some(BoolFalseTag), +// u if u == FwdEdgeTag as u64 => Some(FwdEdgeTag), +// u if u == BwdEdgeTag as u64 => Some(BwdEdgeTag), +// u if u == IntTag as u64 => Some(IntTag), +// u if u == FloatTag as u64 => Some(FloatTag), +// u if u == StringTag as u64 => Some(StringTag), +// u if u == UIntTag as u64 => Some(UIntTag), +// u if u == ListTag as u64 => Some(ListTag), +// u if u == DictTag as u64 => Some(DictTag), +// u if u == UuidTag as u64 => Some(UuidTag), +// _ => None +// } +// } +// +// #[inline] +// pub fn compare_varint(&mut self, other: &mut Self) -> Ordering { +// self.parse_varint().expect( +// "Failed to parse VarInt when comparing" +// ).cmp(&other.parse_varint().expect( +// "Failed to parse VarInt when comparing" +// )) +// } +// +// #[inline] +// 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 +// }) +// } +// +// #[inline] +// pub fn compare_zigzag(&mut self, other: &mut Self) -> Ordering { +// self.parse_zigzag().expect( +// "Failed to parse ZigZag when comparing" +// ).cmp(&other.parse_zigzag().expect( +// "Failed to parse ZigZag when comparing" +// )) +// } +// +// #[inline] +// pub fn parse_float(&mut self) -> Option { +// let buf = self.advance(8)?.try_into().ok()?; +// Some(f64::from_be_bytes(buf)) +// } +// +// #[inline] +// pub fn parse_uuid(&mut self) -> Option { +// Uuid::from_slice(self.advance(16)?).ok() +// } +// +// #[inline] +// pub fn compare_float(&mut self, other: &mut Self) -> Ordering { +// OrderedFloat(self.parse_float().expect( +// "Failed to parse Float when comparing" +// )).cmp(&OrderedFloat(other.parse_float().expect( +// "Failed to parse Float when comparing" +// ))) +// } +// // This should first compare UUID version, then for V1, compare the timestamps +// #[inline] +// pub fn compare_uuid(&mut self, other: &mut Self) -> Ordering { +// let ua = self.parse_uuid().expect( +// "Failed to parse Uuid when comparing" +// ); +// let (a3, a2, a1, a4) = ua.as_fields(); +// let ub = other.parse_uuid().expect( +// "Failed to parse Uuid when comparing" +// ); +// let (b3, b2, b1, b4) = ub.as_fields(); +// if let x @ (Greater | Less) = a1.cmp(&b1) { return x; } +// if let x @ (Greater | Less) = a2.cmp(&b2) { return x; } +// if let x @ (Greater | Less) = a3.cmp(&b3) { return x; } +// a4.cmp(b4) +// } +// +// #[inline] +// 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)) +// // } +// std::str::from_utf8(bytes).ok() +// } +// +// #[inline] +// pub fn compare_string(&mut self, other: &mut Self) -> Ordering { +// let len_a = self.parse_varint().expect("Failed to get String length when comparing"); +// let len_b = other.parse_varint().expect("Failed to get String length when comparing"); +// for _ in 0..min(len_a, len_b) { +// let byte_a = self.advance(1).expect("Unexpected end of String when comparing")[0]; +// let byte_b = other.advance(1).expect("Unexpected end of String when comparing")[0]; +// if let x @ (Greater | Less) = byte_a.cmp(&byte_b) { return x; } +// } +// 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> { +// use ValueTag::*; +// use Value::*; +// use EdgeDirKind::*; +// +// match self.parse_value_tag()? { +// NullTag => Some(Null), +// BoolTrueTag => Some(Bool(true)), +// BoolFalseTag => Some(Bool(false)), +// FwdEdgeTag => Some(EdgeDir(FwdEdgeDir)), +// BwdEdgeTag => Some(EdgeDir(BwdEdgeDir)), +// IntTag => Some(Int(self.parse_zigzag()?)), +// FloatTag => Some(Float(self.parse_float()?)), +// StringTag => Some(Text(Arc::new(Cow::from(self.parse_string()?)))), +// UIntTag => Some(UInt(self.parse_varint()?)), +// ListTag => Some(List(Arc::new(self.parse_list()?))), +// DictTag => Some(Dict(Arc::new(self.parse_dict()?))), +// UuidTag => Some(Uuid(self.parse_uuid()?)) +// } +// } +// pub fn compare_value(&mut self, other: &mut Self) -> Ordering { +// use ValueTag::*; +// +// match (self.parse_value_tag(), other.parse_value_tag()) { +// (None, None) => Equal, +// (None, Some(_)) => Less, +// (Some(_), None) => Greater, +// (Some(type_a), Some(type_b)) => { +// if let x @ (Greater | Less) = type_a.cmp(&type_b) { return x; } +// match type_a { +// IntTag => self.compare_zigzag(other), +// FloatTag => self.compare_float(other), +// StringTag => self.compare_string(other), +// UIntTag => self.compare_varint(other), +// ListTag => self.compare_list(other), +// DictTag => self.compare_dict(other), +// UuidTag => self.compare_uuid(other), +// NullTag | BoolTrueTag | BoolFalseTag | FwdEdgeTag | BwdEdgeTag => Equal +// } +// } +// } +// } +// pub fn compare_list(&mut self, other: &mut Self) -> Ordering { +// let len_a = self.parse_varint().expect("Failed to get List length when comparing"); +// let len_b = other.parse_varint().expect("Failed to get List length when comparing"); +// for _ in 0..min(len_a, len_b) { +// if let x @ (Greater | Less) = self.compare_value(other) { return x; } +// } +// len_a.cmp(&len_b) +// } +// pub fn parse_dict(&mut self) -> Option, Value<'a>>> { +// let l = self.parse_varint()?; +// let mut ret = BTreeMap::new(); +// +// 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().expect("Failed to get Dict length when comparing"); +// let len_b = other.parse_varint().expect("Failed to get Dict length when comparing"); +// for _ in 0..min(len_a, len_b) { +// if let x @ (Greater | Less) = self.compare_string(other) { return x; } +// if let x @ (Greater | Less) = self.compare_value(other) { return x; } +// } +// len_a.cmp(&len_b) +// } +// } +// +// pub struct ByteArrayBuilder> { +// byte_writer: T, +// } +// +// impl> AsRef<[u8]> for ByteArrayBuilder { +// fn as_ref(&self) -> &[u8] { +// self.byte_writer.as_ref() +// } +// } +// +// impl ByteArrayBuilder> { +// pub fn default() -> Self { Self { byte_writer: vec![] } } +// pub fn with_capacity(size: usize) -> Self { +// Self::new(Vec::with_capacity(size)) +// } +// } +// +// impl> ByteArrayBuilder { +// pub fn get(self) -> T { +// self.byte_writer +// } +// +// pub fn new(byte_writer: T) -> Self { +// Self { byte_writer } +// } +// +// #[inline] +// pub fn build_varint(&mut self, u: u64) -> &mut Self { +// let mut u = u; +// while u > 0b01111111 { +// self.byte_writer.write_all(&[0b10000000 | (u as u8 & 0b01111111)]).expect( +// "Failed to write when building VarInt" +// ); +// u >>= 7; +// } +// self.byte_writer.write_all(&[u as u8]).expect( +// "Failed to write when building Varint" +// ); +// self +// } +// +// #[inline] +// pub fn build_zigzag(&mut self, i: i64) -> &mut Self { +// 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); +// self +// } +// +// #[inline] +// pub fn build_float(&mut self, f: f64) -> &mut Self { +// self.byte_writer.write_all(&f.to_be_bytes()).expect( +// "Failed to write when building Float" +// ); +// self +// } +// +// #[inline] +// pub fn build_uuid(&mut self, u: Uuid) -> &mut Self { +// self.byte_writer.write_all(u.as_bytes()).expect( +// "Failed to write when building Uuid" +// ); +// self +// } +// +// #[inline] +// pub fn build_string(&mut self, s: &str) -> &mut Self { +// self.build_varint(s.len() as u64); +// self.byte_writer.write_all(s.as_bytes()).expect("Failed to write when building String"); +// self +// } +// +// #[inline] +// pub fn build_tag(&mut self, t: ValueTag) -> &mut Self { +// self.byte_writer.write_all(&[t as u8]).expect("Failed to write when building Tag"); +// self +// } +// +// pub fn build_value(&mut self, v: &Value) -> &mut Self { +// use ValueTag::*; +// +// match v { +// Value::Null => self.build_tag(NullTag), +// Value::Bool(b) => self.build_tag(if *b { BoolTrueTag } else { BoolFalseTag }), +// Value::EdgeDir(e) => self.build_tag(match e { +// EdgeDirKind::FwdEdgeDir => { FwdEdgeTag } +// EdgeDirKind::BwdEdgeDir => { BwdEdgeTag } +// }), +// Value::UInt(u) => { +// self.build_tag(UIntTag).build_varint(*u) +// } +// Value::Int(i) => { +// self.build_tag(IntTag).build_zigzag(*i) +// } +// Value::Float(f) => { +// self.build_tag(FloatTag).build_float(*f) +// } +// Value::Text(s) => { +// self.build_tag(StringTag).build_string(s) +// } +// Value::List(l) => { +// self.build_tag(ListTag).build_list(l) +// } +// Value::Dict(d) => { +// self.build_tag(DictTag).build_dict(d) +// } +// Value::Uuid(u) => { +// self.build_tag(UuidTag).build_uuid(*u) +// } +// } +// } +// +// pub fn build_list(&mut self, l: &[Value]) -> &mut Self { +// self.build_varint(l.len() as u64); +// for el in l { +// self.build_value(el); +// } +// self +// } +// +// pub fn build_dict(&mut self, d: &BTreeMap, Value>) -> &mut Self { +// self.build_varint(d.len() as u64); +// for (k, v) in d { +// self.build_string(k).build_value(v); +// } +// self +// } +// } +// +// +// pub fn cozo_comparator_v1(a: &[u8], b: &[u8]) -> i8 { +// let mut ba = &mut ByteArrayParser { bytes: a, current: 0 }; +// let mut bb = &mut ByteArrayParser { bytes: b, current: 0 }; +// match ba.compare_varint(&mut bb) { +// Less => return -1, +// Greater => return 1, +// Equal => {} +// } +// match cmp_data(&mut ba, &mut bb) { +// Less => -1, +// Equal => 0, +// Greater => 1 +// } +// } +// +// 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 Equal, +// (true, false) => return Less, +// (false, true) => return Greater, +// (false, false) => () +// } +// if let x @ (Greater | Less) = pa.compare_value(pb) { return x; } +// } +// } +// +// +// impl<'a> Value<'a> { +// pub fn owned_clone(&self) -> StaticValue { +// use Value::*; +// +// match self { +// Null => Null, +// Bool(b) => Bool(*b), +// EdgeDir(dir) => EdgeDir(*dir), +// UInt(u) => UInt(*u), +// Int(i) => Int(*i), +// Float(f) => Float(*f), +// // Text(s) => Text(Arc::new(Cow::Owned(s.into_owned()))), +// Text(s) => todo!(), +// List(l) => { +// let mut inner = Vec::with_capacity(l.len()); +// +// for el in l.iter() { +// inner.push(el.owned_clone()) +// } +// List(Arc::new(inner)) +// } +// Dict(d) => { +// let mut inner = BTreeMap::new(); +// for (k, v) in d.iter() { +// let new_k = Cow::from(k.clone().into_owned()); +// inner.insert(new_k, v.owned_clone()); +// } +// Dict(Arc::new(inner)) +// } +// Uuid(u) => Uuid(*u), +// } +// } +// } +// +// #[derive(Clone, Debug)] +// pub struct CoercionError<'a> { +// pub msg: String, +// pub val: Value<'a>, +// } +// +// impl Typing { +// pub fn coerce<'a>(&self, v: Value<'a>) -> Result, CoercionError<'a>> { +// // TODO +// Ok(v) +// } +// } +// +// pub struct CozoKey<'a> { +// pub table_id: i64, +// 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 builder = ByteArrayBuilder::default(); +// builder.build_zigzag(i); +// let mut parser = ByteArrayParser::new(&builder); +// 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); +// } +// +// +// #[test] +// fn size() { +// println!("{:?}", std::mem::size_of::()); +// println!("{:?}", std::mem::size_of::()); +// println!("{:?}", std::mem::size_of::()); +// println!("{:?}", std::mem::size_of::, Value>>()); +// println!("{:?}", std::mem::size_of::>()); +// println!("{:?}", std::mem::size_of::>()); +// println!("{:?}", std::mem::size_of::>>()); +// println!("{:?}", std::mem::size_of::>>()); +// println!("{:?}", std::mem::size_of::()); +// println!("{:?}", std::mem::size_of::<&str>()); +// } +// }