use std::fmt;
use std::sync::Arc;
use crate::commands::buffer::Buffer;
use crate::expressions::Expression;
use crate::msgpack::encoder::{pack_array_begin, pack_integer};
use crate::operations::{Operation, OperationBin, OperationData, OperationType};
use crate::Result;
#[derive(Clone, Copy)]
pub enum ExpWriteFlags {
Default = 0,
CreateOnly = 1 << 0,
UpdateOnly = 1 << 1,
AllowDelete = 1 << 2,
PolicyNoFail = 1 << 3,
EvalNoFail = 1 << 4,
}
pub trait ToExpWriteFlagBitmask {
fn to_bitmask(self) -> i64;
}
impl ToExpWriteFlagBitmask for ExpWriteFlags {
fn to_bitmask(self) -> i64 {
self as i64
}
}
impl<T: IntoIterator<Item = ExpWriteFlags>> ToExpWriteFlagBitmask for T {
fn to_bitmask(self) -> i64 {
let mut out = 0;
for val in self {
out |= val.to_bitmask();
}
out
}
}
pub(crate) type ExpressionEncoder =
Arc<dyn Fn(&mut Option<&mut Buffer>, &ExpOperation) -> Result<usize> + Send + Sync + 'static>;
#[derive(Clone)]
pub(crate) struct ExpOperation {
pub encoder: ExpressionEncoder,
pub policy: i64,
pub exp: Expression,
}
impl ExpOperation {
pub(crate) fn estimate_size(&self) -> Result<usize> {
let size: usize = (self.encoder)(&mut None, self)?;
Ok(size)
}
pub(crate) fn write_to(&self, buffer: &mut Buffer) -> Result<usize> {
let size: usize = (self.encoder)(&mut Some(buffer), self)?;
Ok(size)
}
}
impl fmt::Debug for ExpOperation {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::result::Result<(), fmt::Error> {
#[derive(Debug)]
#[allow(unused)]
struct ExpOperation<'a> {
policy: &'a i64,
exp: &'a Expression,
}
let Self {
encoder: _,
policy,
exp,
} = self;
fmt::Debug::fmt(&ExpOperation { policy, exp }, f)
}
}
pub enum ExpReadFlags {
Default = 0,
EvalNoFail = 1 << 4,
}
pub trait ToExpReadFlagBitmask {
fn to_bitmask(self) -> i64;
}
impl ToExpReadFlagBitmask for ExpReadFlags {
fn to_bitmask(self) -> i64 {
self as i64
}
}
impl<T: IntoIterator<Item = ExpReadFlags>> ToExpReadFlagBitmask for T {
fn to_bitmask(self) -> i64 {
let mut out = 0;
for val in self {
out |= val.to_bitmask();
}
out
}
}
pub fn write_exp<E: ToExpWriteFlagBitmask>(bin: &str, exp: Expression, flags: E) -> Operation {
let op = ExpOperation {
encoder: Arc::new(pack_write_exp),
policy: flags.to_bitmask(),
exp,
};
Operation {
op: OperationType::ExpWrite,
ctx: vec![],
bin: OperationBin::Name(bin.into()),
data: OperationData::EXPOp(op),
}
}
pub fn read_exp<E: ToExpReadFlagBitmask>(name: &str, exp: Expression, flags: E) -> Operation {
let op = ExpOperation {
encoder: Arc::new(pack_read_exp),
policy: flags.to_bitmask(),
exp,
};
Operation {
op: OperationType::ExpRead,
ctx: vec![],
bin: OperationBin::Name(name.into()),
data: OperationData::EXPOp(op),
}
}
fn pack_write_exp(buf: &mut Option<&mut Buffer>, exp_op: &ExpOperation) -> Result<usize> {
let mut size = 0;
size += pack_array_begin(buf, 2);
size += exp_op.exp.pack(buf)?;
size += pack_integer(buf, exp_op.policy);
Ok(size)
}
fn pack_read_exp(buf: &mut Option<&mut Buffer>, exp_op: &ExpOperation) -> Result<usize> {
let mut size = 0;
size += pack_array_begin(buf, 2);
size += exp_op.exp.pack(buf)?;
size += pack_integer(buf, exp_op.policy);
Ok(size)
}