pub mod bitwise;
pub mod hll;
pub mod lists;
pub mod maps;
pub mod regex_flag;
use crate::commands::buffer::Buffer;
use crate::errors::Result;
use crate::msgpack::encoder::{pack_array_begin, pack_integer, pack_raw_string, pack_value};
use crate::operations::cdt_context::CdtContext;
use crate::{ParticleType, Value};
use std::collections::HashMap;
use std::fmt::Debug;
#[derive(Debug, Clone, Copy)]
pub enum ExpType {
NIL = 0,
BOOL = 1,
INT = 2,
STRING = 3,
LIST = 4,
MAP = 5,
BLOB = 6,
FLOAT = 7,
GEO = 8,
HLL = 9,
}
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub enum ExpOp {
Unknown = 0,
EQ = 1,
NE = 2,
GT = 3,
GE = 4,
LT = 5,
LE = 6,
Regex = 7,
Geo = 8,
And = 16,
Or = 17,
Not = 18,
Xor = 19,
Add = 20,
Sub = 21,
Mul = 22,
Div = 23,
Pow = 24,
Log = 25,
Mod = 26,
Abs = 27,
Floor = 28,
Ceil = 29,
ToInt = 30,
ToFloat = 31,
IntAnd = 32,
IntOr = 33,
IntXor = 34,
IntNot = 35,
IntLshift = 36,
IntRshift = 37,
IntARshift = 38,
IntCount = 39,
IntLscan = 40,
IntRscan = 41,
Min = 50,
Max = 51,
DigestModulo = 64,
DeviceSize = 65,
LastUpdate = 66,
SinceUpdate = 67,
VoidTime = 68,
TTL = 69,
SetName = 70,
KeyExists = 71,
IsTombstone = 72,
Key = 80,
Bin = 81,
BinType = 82,
Cond = 123,
Var = 124,
Let = 125,
Quoted = 126,
Call = 127,
}
#[doc(hidden)]
pub const MODIFY: i64 = 0x40;
#[derive(Debug, Clone)]
#[doc(hidden)]
pub enum ExpressionArgument {
Value(Value),
FilterExpression(FilterExpression),
Context(Vec<CdtContext>),
}
#[derive(Debug, Clone)]
pub struct FilterExpression {
cmd: Option<ExpOp>,
val: Option<Value>,
bin: Option<Box<FilterExpression>>,
flags: Option<i64>,
module: Option<ExpType>,
exps: Option<Vec<FilterExpression>>,
arguments: Option<Vec<ExpressionArgument>>,
}
#[doc(hidden)]
impl FilterExpression {
fn new(
cmd: Option<ExpOp>,
val: Option<Value>,
bin: Option<FilterExpression>,
flags: Option<i64>,
module: Option<ExpType>,
exps: Option<Vec<FilterExpression>>,
) -> FilterExpression {
let bin = bin.map(Box::new);
FilterExpression {
cmd,
val,
bin,
flags,
module,
exps,
arguments: None,
}
}
fn pack_expression(
&self,
exps: &[FilterExpression],
buf: &mut Option<&mut Buffer>,
) -> Result<usize> {
let mut size = 0;
if let Some(val) = &self.val {
size += pack_raw_string(buf, &val.to_string())?;
size += exps[0].pack(buf)?;
} else {
match self.cmd.unwrap() {
ExpOp::Let => {
let count = (exps.len() - 1) * 2 + 2;
size += pack_array_begin(buf, count)?;
}
_ => {
size += pack_array_begin(buf, exps.len() + 1)?;
}
}
size += pack_integer(buf, self.cmd.unwrap() as i64)?;
for exp in exps {
size += exp.pack(buf)?;
}
}
Ok(size)
}
fn pack_command(&self, cmd: ExpOp, buf: &mut Option<&mut Buffer>) -> Result<usize> {
let mut size = 0;
match cmd {
ExpOp::Regex => {
size += pack_array_begin(buf, 4)?;
size += pack_integer(buf, cmd as i64)?;
size += pack_integer(buf, self.flags.unwrap())?;
size += pack_raw_string(buf, &self.val.clone().unwrap().to_string())?;
size += self.bin.clone().unwrap().pack(buf)?;
}
ExpOp::Call => {
size += pack_array_begin(buf, 5)?;
size += pack_integer(buf, cmd as i64)?;
size += pack_integer(buf, self.module.unwrap() as i64)?;
size += pack_integer(buf, self.flags.unwrap())?;
if let Some(args) = &self.arguments {
let mut len = 0;
for arg in args {
match arg {
ExpressionArgument::Value(_)
| ExpressionArgument::FilterExpression(_) => len += 1,
ExpressionArgument::Context(ctx) => {
if !ctx.is_empty() {
size += pack_array_begin(buf, 3)?;
size += pack_integer(buf, 0xff)?;
size += pack_array_begin(buf, ctx.len() * 2)?;
for c in ctx {
size += pack_integer(buf, i64::from(c.id))?;
size += pack_value(buf, &c.value)?;
}
}
}
}
}
size += pack_array_begin(buf, len)?;
for arg in args {
match arg {
ExpressionArgument::Value(val) => {
size += pack_value(buf, val)?;
}
ExpressionArgument::FilterExpression(cmd) => {
size += cmd.pack(buf)?;
}
_ => {}
}
}
} else {
size += pack_value(buf, &self.val.clone().unwrap())?;
}
size += self.bin.clone().unwrap().pack(buf)?;
}
ExpOp::Bin => {
size += pack_array_begin(buf, 3)?;
size += pack_integer(buf, cmd as i64)?;
size += pack_integer(buf, self.module.unwrap() as i64)?;
size += pack_raw_string(buf, &self.val.clone().unwrap().to_string())?;
}
ExpOp::BinType | ExpOp::Var => {
size += pack_array_begin(buf, 2)?;
size += pack_integer(buf, cmd as i64)?;
size += pack_raw_string(buf, &self.val.clone().unwrap().to_string())?;
}
_ => {
if let Some(value) = &self.val {
size += pack_array_begin(buf, 2)?;
size += pack_integer(buf, cmd as i64)?;
size += pack_value(buf, value)?;
} else {
size += pack_array_begin(buf, 1)?;
size += pack_integer(buf, cmd as i64)?;
}
}
}
Ok(size)
}
fn pack_value(&self, buf: &mut Option<&mut Buffer>) -> Result<usize> {
pack_value(buf, &self.val.clone().unwrap())
}
pub fn pack(&self, buf: &mut Option<&mut Buffer>) -> Result<usize> {
let mut size = 0;
if let Some(exps) = &self.exps {
size += self.pack_expression(exps, buf)?;
} else if let Some(cmd) = self.cmd {
size += self.pack_command(cmd, buf)?;
} else {
size += self.pack_value(buf)?;
}
Ok(size)
}
}
pub fn key(exp_type: ExpType) -> FilterExpression {
FilterExpression::new(
Some(ExpOp::Key),
Some(Value::from(exp_type as i64)),
None,
None,
None,
None,
)
}
pub fn key_exists() -> FilterExpression {
FilterExpression::new(Some(ExpOp::KeyExists), None, None, None, None, None)
}
pub fn int_bin(name: String) -> FilterExpression {
FilterExpression::new(
Some(ExpOp::Bin),
Some(Value::from(name)),
None,
None,
Some(ExpType::INT),
None,
)
}
pub fn string_bin(name: String) -> FilterExpression {
FilterExpression::new(
Some(ExpOp::Bin),
Some(Value::from(name)),
None,
None,
Some(ExpType::STRING),
None,
)
}
pub fn blob_bin(name: String) -> FilterExpression {
FilterExpression::new(
Some(ExpOp::Bin),
Some(Value::from(name)),
None,
None,
Some(ExpType::BLOB),
None,
)
}
pub fn float_bin(name: String) -> FilterExpression {
FilterExpression::new(
Some(ExpOp::Bin),
Some(Value::from(name)),
None,
None,
Some(ExpType::FLOAT),
None,
)
}
pub fn geo_bin(name: String) -> FilterExpression {
FilterExpression::new(
Some(ExpOp::Bin),
Some(Value::from(name)),
None,
None,
Some(ExpType::GEO),
None,
)
}
pub fn list_bin(name: String) -> FilterExpression {
FilterExpression::new(
Some(ExpOp::Bin),
Some(Value::from(name)),
None,
None,
Some(ExpType::LIST),
None,
)
}
pub fn map_bin(name: String) -> FilterExpression {
FilterExpression::new(
Some(ExpOp::Bin),
Some(Value::from(name)),
None,
None,
Some(ExpType::MAP),
None,
)
}
pub fn hll_bin(name: String) -> FilterExpression {
FilterExpression::new(
Some(ExpOp::Bin),
Some(Value::from(name)),
None,
None,
Some(ExpType::HLL),
None,
)
}
pub fn bin_exists(name: String) -> FilterExpression {
ne(bin_type(name), int_val(ParticleType::NULL as i64))
}
pub fn bin_type(name: String) -> FilterExpression {
FilterExpression::new(
Some(ExpOp::BinType),
Some(Value::from(name)),
None,
None,
None,
None,
)
}
pub fn set_name() -> FilterExpression {
FilterExpression::new(Some(ExpOp::SetName), None, None, None, None, None)
}
pub fn device_size() -> FilterExpression {
FilterExpression::new(Some(ExpOp::DeviceSize), None, None, None, None, None)
}
pub fn last_update() -> FilterExpression {
FilterExpression::new(Some(ExpOp::LastUpdate), None, None, None, None, None)
}
pub fn since_update() -> FilterExpression {
FilterExpression::new(Some(ExpOp::SinceUpdate), None, None, None, None, None)
}
pub fn void_time() -> FilterExpression {
FilterExpression::new(Some(ExpOp::VoidTime), None, None, None, None, None)
}
pub fn ttl() -> FilterExpression {
FilterExpression::new(Some(ExpOp::TTL), None, None, None, None, None)
}
pub fn is_tombstone() -> FilterExpression {
FilterExpression::new(Some(ExpOp::IsTombstone), None, None, None, None, None)
}
pub fn digest_modulo(modulo: i64) -> FilterExpression {
FilterExpression::new(
Some(ExpOp::DigestModulo),
Some(Value::from(modulo)),
None,
None,
None,
None,
)
}
pub fn regex_compare(regex: String, flags: i64, bin: FilterExpression) -> FilterExpression {
FilterExpression::new(
Some(ExpOp::Regex),
Some(Value::from(regex)),
Some(bin),
Some(flags),
None,
None,
)
}
pub fn geo_compare(left: FilterExpression, right: FilterExpression) -> FilterExpression {
FilterExpression::new(
Some(ExpOp::Geo),
None,
None,
None,
None,
Some(vec![left, right]),
)
}
pub fn int_val(val: i64) -> FilterExpression {
FilterExpression::new(None, Some(Value::from(val)), None, None, None, None)
}
pub fn bool_val(val: bool) -> FilterExpression {
FilterExpression::new(None, Some(Value::from(val)), None, None, None, None)
}
pub fn string_val(val: String) -> FilterExpression {
FilterExpression::new(None, Some(Value::from(val)), None, None, None, None)
}
pub fn float_val(val: f64) -> FilterExpression {
FilterExpression::new(None, Some(Value::from(val)), None, None, None, None)
}
pub fn blob_val(val: Vec<u8>) -> FilterExpression {
FilterExpression::new(None, Some(Value::from(val)), None, None, None, None)
}
pub fn list_val(val: Vec<Value>) -> FilterExpression {
FilterExpression::new(
Some(ExpOp::Quoted),
Some(Value::from(val)),
None,
None,
None,
None,
)
}
#[allow(clippy::implicit_hasher)]
pub fn map_val(val: HashMap<Value, Value>) -> FilterExpression {
FilterExpression::new(None, Some(Value::from(val)), None, None, None, None)
}
pub fn geo_val(val: String) -> FilterExpression {
FilterExpression::new(None, Some(Value::from(val)), None, None, None, None)
}
pub fn nil() -> FilterExpression {
FilterExpression::new(None, Some(Value::Nil), None, None, None, None)
}
pub fn not(exp: FilterExpression) -> FilterExpression {
FilterExpression {
cmd: Some(ExpOp::Not),
val: None,
bin: None,
flags: None,
module: None,
exps: Some(vec![exp]),
arguments: None,
}
}
pub const fn and(exps: Vec<FilterExpression>) -> FilterExpression {
FilterExpression {
cmd: Some(ExpOp::And),
val: None,
bin: None,
flags: None,
module: None,
exps: Some(exps),
arguments: None,
}
}
pub const fn or(exps: Vec<FilterExpression>) -> FilterExpression {
FilterExpression {
cmd: Some(ExpOp::Or),
val: None,
bin: None,
flags: None,
module: None,
exps: Some(exps),
arguments: None,
}
}
pub fn eq(left: FilterExpression, right: FilterExpression) -> FilterExpression {
FilterExpression {
cmd: Some(ExpOp::EQ),
val: None,
bin: None,
flags: None,
module: None,
exps: Some(vec![left, right]),
arguments: None,
}
}
pub fn ne(left: FilterExpression, right: FilterExpression) -> FilterExpression {
FilterExpression {
cmd: Some(ExpOp::NE),
val: None,
bin: None,
flags: None,
module: None,
exps: Some(vec![left, right]),
arguments: None,
}
}
pub fn gt(left: FilterExpression, right: FilterExpression) -> FilterExpression {
FilterExpression {
cmd: Some(ExpOp::GT),
val: None,
bin: None,
flags: None,
module: None,
exps: Some(vec![left, right]),
arguments: None,
}
}
pub fn ge(left: FilterExpression, right: FilterExpression) -> FilterExpression {
FilterExpression {
cmd: Some(ExpOp::GE),
val: None,
bin: None,
flags: None,
module: None,
exps: Some(vec![left, right]),
arguments: None,
}
}
pub fn lt(left: FilterExpression, right: FilterExpression) -> FilterExpression {
FilterExpression {
cmd: Some(ExpOp::LT),
val: None,
bin: None,
flags: None,
module: None,
exps: Some(vec![left, right]),
arguments: None,
}
}
pub fn le(left: FilterExpression, right: FilterExpression) -> FilterExpression {
FilterExpression {
cmd: Some(ExpOp::LE),
val: None,
bin: None,
flags: None,
module: None,
exps: Some(vec![left, right]),
arguments: None,
}
}
pub const fn num_add(exps: Vec<FilterExpression>) -> FilterExpression {
FilterExpression {
cmd: Some(ExpOp::Add),
val: None,
bin: None,
flags: None,
module: None,
exps: Some(exps),
arguments: None,
}
}
pub const fn num_sub(exps: Vec<FilterExpression>) -> FilterExpression {
FilterExpression {
cmd: Some(ExpOp::Sub),
val: None,
bin: None,
flags: None,
module: None,
exps: Some(exps),
arguments: None,
}
}
pub const fn num_mul(exps: Vec<FilterExpression>) -> FilterExpression {
FilterExpression {
cmd: Some(ExpOp::Mul),
val: None,
bin: None,
flags: None,
module: None,
exps: Some(exps),
arguments: None,
}
}
pub const fn num_div(exps: Vec<FilterExpression>) -> FilterExpression {
FilterExpression {
cmd: Some(ExpOp::Div),
val: None,
bin: None,
flags: None,
module: None,
exps: Some(exps),
arguments: None,
}
}
pub fn num_pow(base: FilterExpression, exponent: FilterExpression) -> FilterExpression {
FilterExpression {
cmd: Some(ExpOp::Pow),
val: None,
bin: None,
flags: None,
module: None,
exps: Some(vec![base, exponent]),
arguments: None,
}
}
pub fn num_log(num: FilterExpression, base: FilterExpression) -> FilterExpression {
FilterExpression {
cmd: Some(ExpOp::Log),
val: None,
bin: None,
flags: None,
module: None,
exps: Some(vec![num, base]),
arguments: None,
}
}
pub fn num_mod(numerator: FilterExpression, denominator: FilterExpression) -> FilterExpression {
FilterExpression {
cmd: Some(ExpOp::Mod),
val: None,
bin: None,
flags: None,
module: None,
exps: Some(vec![numerator, denominator]),
arguments: None,
}
}
pub fn num_abs(value: FilterExpression) -> FilterExpression {
FilterExpression {
cmd: Some(ExpOp::Abs),
val: None,
bin: None,
flags: None,
module: None,
exps: Some(vec![value]),
arguments: None,
}
}
pub fn num_floor(num: FilterExpression) -> FilterExpression {
FilterExpression {
cmd: Some(ExpOp::Floor),
val: None,
bin: None,
flags: None,
module: None,
exps: Some(vec![num]),
arguments: None,
}
}
pub fn num_ceil(num: FilterExpression) -> FilterExpression {
FilterExpression {
cmd: Some(ExpOp::Ceil),
val: None,
bin: None,
flags: None,
module: None,
exps: Some(vec![num]),
arguments: None,
}
}
pub fn to_int(num: FilterExpression) -> FilterExpression {
FilterExpression {
cmd: Some(ExpOp::ToInt),
val: None,
bin: None,
flags: None,
module: None,
exps: Some(vec![num]),
arguments: None,
}
}
pub fn to_float(num: FilterExpression) -> FilterExpression {
FilterExpression {
cmd: Some(ExpOp::ToFloat),
val: None,
bin: None,
flags: None,
module: None,
exps: Some(vec![num]),
arguments: None,
}
}
pub const fn int_and(exps: Vec<FilterExpression>) -> FilterExpression {
FilterExpression {
cmd: Some(ExpOp::IntAnd),
val: None,
bin: None,
flags: None,
module: None,
exps: Some(exps),
arguments: None,
}
}
pub const fn int_xor(exps: Vec<FilterExpression>) -> FilterExpression {
FilterExpression {
cmd: Some(ExpOp::IntXor),
val: None,
bin: None,
flags: None,
module: None,
exps: Some(exps),
arguments: None,
}
}
pub fn int_not(exp: FilterExpression) -> FilterExpression {
FilterExpression {
cmd: Some(ExpOp::IntNot),
val: None,
bin: None,
flags: None,
module: None,
exps: Some(vec![exp]),
arguments: None,
}
}
pub fn int_lshift(value: FilterExpression, shift: FilterExpression) -> FilterExpression {
FilterExpression {
cmd: Some(ExpOp::IntLshift),
val: None,
bin: None,
flags: None,
module: None,
exps: Some(vec![value, shift]),
arguments: None,
}
}
pub fn int_rshift(value: FilterExpression, shift: FilterExpression) -> FilterExpression {
FilterExpression {
cmd: Some(ExpOp::IntRshift),
val: None,
bin: None,
flags: None,
module: None,
exps: Some(vec![value, shift]),
arguments: None,
}
}
pub fn int_arshift(value: FilterExpression, shift: FilterExpression) -> FilterExpression {
FilterExpression {
cmd: Some(ExpOp::IntARshift),
val: None,
bin: None,
flags: None,
module: None,
exps: Some(vec![value, shift]),
arguments: None,
}
}
pub fn int_count(exp: FilterExpression) -> FilterExpression {
FilterExpression {
cmd: Some(ExpOp::IntCount),
val: None,
bin: None,
flags: None,
module: None,
exps: Some(vec![exp]),
arguments: None,
}
}
pub fn int_lscan(value: FilterExpression, search: FilterExpression) -> FilterExpression {
FilterExpression {
cmd: Some(ExpOp::IntLscan),
val: None,
bin: None,
flags: None,
module: None,
exps: Some(vec![value, search]),
arguments: None,
}
}
pub fn int_rscan(value: FilterExpression, search: FilterExpression) -> FilterExpression {
FilterExpression {
cmd: Some(ExpOp::IntRscan),
val: None,
bin: None,
flags: None,
module: None,
exps: Some(vec![value, search]),
arguments: None,
}
}
pub const fn min(exps: Vec<FilterExpression>) -> FilterExpression {
FilterExpression {
cmd: Some(ExpOp::Min),
val: None,
bin: None,
flags: None,
module: None,
exps: Some(exps),
arguments: None,
}
}
pub const fn max(exps: Vec<FilterExpression>) -> FilterExpression {
FilterExpression {
cmd: Some(ExpOp::Max),
val: None,
bin: None,
flags: None,
module: None,
exps: Some(exps),
arguments: None,
}
}
pub const fn cond(exps: Vec<FilterExpression>) -> FilterExpression {
FilterExpression {
cmd: Some(ExpOp::Cond),
val: None,
bin: None,
flags: None,
module: None,
exps: Some(exps),
arguments: None,
}
}
pub const fn exp_let(exps: Vec<FilterExpression>) -> FilterExpression {
FilterExpression {
cmd: Some(ExpOp::Let),
val: None,
bin: None,
flags: None,
module: None,
exps: Some(exps),
arguments: None,
}
}
pub fn def(name: String, value: FilterExpression) -> FilterExpression {
FilterExpression {
cmd: None,
val: Some(Value::from(name)),
bin: None,
flags: None,
module: None,
exps: Some(vec![value]),
arguments: None,
}
}
pub fn var(name: String) -> FilterExpression {
FilterExpression {
cmd: Some(ExpOp::Var),
val: Some(Value::from(name)),
bin: None,
flags: None,
module: None,
exps: None,
arguments: None,
}
}
pub const fn unknown() -> FilterExpression {
FilterExpression {
cmd: Some(ExpOp::Unknown),
val: None,
bin: None,
flags: None,
module: None,
exps: None,
arguments: None,
}
}