use crate::expressions::{nil, ExpOp, ExpType, Expression, ExpressionArgument, MODIFY};
use crate::operations::cdt_context::{CdtContext, CtxType};
use crate::operations::lists::{
CdtListOpType, ListPolicy, ListReturnType, ListSortFlags, ToListReturnTypeBitmask,
};
use crate::Value;
const MODULE: i64 = 0;
pub fn append(
policy: ListPolicy,
value: Expression,
bin: Expression,
ctx: &[CdtContext],
) -> Expression {
let args = vec![
ExpressionArgument::Value(Value::from(CdtListOpType::Append as i64)),
ExpressionArgument::FilterExpression(value),
ExpressionArgument::Value(Value::from(policy.attributes as u8)),
ExpressionArgument::Value(Value::from(policy.flags)),
ExpressionArgument::Context(ctx.to_vec()),
];
add_write(bin, ctx, args)
}
pub fn append_items(
policy: ListPolicy,
list: Expression,
bin: Expression,
ctx: &[CdtContext],
) -> Expression {
let args = vec![
ExpressionArgument::Value(Value::from(CdtListOpType::AppendItems as i64)),
ExpressionArgument::FilterExpression(list),
ExpressionArgument::Value(Value::from(policy.attributes as u8)),
ExpressionArgument::Value(Value::from(policy.flags)),
ExpressionArgument::Context(ctx.to_vec()),
];
add_write(bin, ctx, args)
}
pub fn insert(
policy: ListPolicy,
index: Expression,
value: Expression,
bin: Expression,
ctx: &[CdtContext],
) -> Expression {
let args = vec![
ExpressionArgument::Value(Value::from(CdtListOpType::Insert as i64)),
ExpressionArgument::FilterExpression(index),
ExpressionArgument::FilterExpression(value),
ExpressionArgument::Value(Value::from(policy.flags)),
ExpressionArgument::Context(ctx.to_vec()),
];
add_write(bin, ctx, args)
}
pub fn insert_items(
policy: ListPolicy,
index: Expression,
list: Expression,
bin: Expression,
ctx: &[CdtContext],
) -> Expression {
let args = vec![
ExpressionArgument::Value(Value::from(CdtListOpType::InsertItems as i64)),
ExpressionArgument::FilterExpression(index),
ExpressionArgument::FilterExpression(list),
ExpressionArgument::Value(Value::from(policy.flags)),
ExpressionArgument::Context(ctx.to_vec()),
];
add_write(bin, ctx, args)
}
pub fn increment(
policy: ListPolicy,
index: Expression,
value: Expression,
bin: Expression,
ctx: &[CdtContext],
) -> Expression {
let args = vec![
ExpressionArgument::Value(Value::from(CdtListOpType::Increment as i64)),
ExpressionArgument::FilterExpression(index),
ExpressionArgument::FilterExpression(value),
ExpressionArgument::Value(Value::from(policy.attributes as u8)),
ExpressionArgument::Value(Value::from(policy.flags)),
ExpressionArgument::Context(ctx.to_vec()),
];
add_write(bin, ctx, args)
}
pub fn set(
policy: ListPolicy,
index: Expression,
value: Expression,
bin: Expression,
ctx: &[CdtContext],
) -> Expression {
let args = vec![
ExpressionArgument::Value(Value::from(CdtListOpType::Set as i64)),
ExpressionArgument::FilterExpression(index),
ExpressionArgument::FilterExpression(value),
ExpressionArgument::Value(Value::from(policy.flags)),
ExpressionArgument::Context(ctx.to_vec()),
];
add_write(bin, ctx, args)
}
pub fn clear(bin: Expression, ctx: &[CdtContext]) -> Expression {
let args = vec![
ExpressionArgument::Value(Value::from(CdtListOpType::Clear as i64)),
ExpressionArgument::Context(ctx.to_vec()),
];
add_write(bin, ctx, args)
}
pub fn sort(sort_flags: ListSortFlags, bin: Expression, ctx: &[CdtContext]) -> Expression {
let args = vec![
ExpressionArgument::Value(Value::from(CdtListOpType::Sort as i64)),
ExpressionArgument::Value(Value::from(sort_flags as u8)),
ExpressionArgument::Context(ctx.to_vec()),
];
add_write(bin, ctx, args)
}
pub fn remove_by_value<TLR: ToListReturnTypeBitmask>(
return_type: TLR,
value: Expression,
bin: Expression,
ctx: &[CdtContext],
) -> Expression {
let args = vec![
ExpressionArgument::Value(Value::from(CdtListOpType::RemoveByValue as i64)),
ExpressionArgument::Value(Value::from(return_type.to_bitmask())),
ExpressionArgument::FilterExpression(value),
ExpressionArgument::Context(ctx.to_vec()),
];
add_write(bin, ctx, args)
}
pub fn remove_by_value_list<TLR: ToListReturnTypeBitmask>(
return_type: TLR,
values: Expression,
bin: Expression,
ctx: &[CdtContext],
) -> Expression {
let args = vec![
ExpressionArgument::Value(Value::from(CdtListOpType::RemoveByValueList as i64)),
ExpressionArgument::Value(Value::from(return_type.to_bitmask())),
ExpressionArgument::FilterExpression(values),
ExpressionArgument::Context(ctx.to_vec()),
];
add_write(bin, ctx, args)
}
pub fn remove_by_value_range<TLR: ToListReturnTypeBitmask>(
return_type: TLR,
value_begin: Option<Expression>,
value_end: Option<Expression>,
bin: Expression,
ctx: &[CdtContext],
) -> Expression {
let mut args = vec![
ExpressionArgument::Context(ctx.to_vec()),
ExpressionArgument::Value(Value::from(CdtListOpType::RemoveByValueInterval as i64)),
ExpressionArgument::Value(Value::from(return_type.to_bitmask())),
];
if let Some(val_beg) = value_begin {
args.push(ExpressionArgument::FilterExpression(val_beg));
} else {
args.push(ExpressionArgument::FilterExpression(nil()));
}
if let Some(val_end) = value_end {
args.push(ExpressionArgument::FilterExpression(val_end));
}
add_write(bin, ctx, args)
}
pub fn remove_by_value_relative_rank_range<TLR: ToListReturnTypeBitmask>(
return_type: TLR,
value: Expression,
rank: Expression,
bin: Expression,
ctx: &[CdtContext],
) -> Expression {
let args = vec![
ExpressionArgument::Value(Value::from(CdtListOpType::RemoveByValueRelRankRange as i64)),
ExpressionArgument::Value(Value::from(return_type.to_bitmask())),
ExpressionArgument::FilterExpression(value),
ExpressionArgument::FilterExpression(rank),
ExpressionArgument::Context(ctx.to_vec()),
];
add_write(bin, ctx, args)
}
pub fn remove_by_value_relative_rank_range_count<TLR: ToListReturnTypeBitmask>(
return_type: TLR,
value: Expression,
rank: Expression,
count: Expression,
bin: Expression,
ctx: &[CdtContext],
) -> Expression {
let args = vec![
ExpressionArgument::Value(Value::from(CdtListOpType::RemoveByValueRelRankRange as i64)),
ExpressionArgument::Value(Value::from(return_type.to_bitmask())),
ExpressionArgument::FilterExpression(value),
ExpressionArgument::FilterExpression(rank),
ExpressionArgument::FilterExpression(count),
ExpressionArgument::Context(ctx.to_vec()),
];
add_write(bin, ctx, args)
}
pub fn remove_by_index<TLR: ToListReturnTypeBitmask>(
return_type: TLR,
index: Expression,
bin: Expression,
ctx: &[CdtContext],
) -> Expression {
let args = vec![
ExpressionArgument::Value(Value::from(CdtListOpType::RemoveByIndex as i64)),
ExpressionArgument::Value(Value::from(return_type.to_bitmask())),
ExpressionArgument::FilterExpression(index),
ExpressionArgument::Context(ctx.to_vec()),
];
add_write(bin, ctx, args)
}
pub fn remove_by_index_range<TLR: ToListReturnTypeBitmask>(
return_type: TLR,
index: Expression,
bin: Expression,
ctx: &[CdtContext],
) -> Expression {
let args = vec![
ExpressionArgument::Value(Value::from(CdtListOpType::RemoveByIndexRange as i64)),
ExpressionArgument::Value(Value::from(return_type.to_bitmask())),
ExpressionArgument::FilterExpression(index),
ExpressionArgument::Context(ctx.to_vec()),
];
add_write(bin, ctx, args)
}
pub fn remove_by_index_range_count<TLR: ToListReturnTypeBitmask>(
return_type: TLR,
index: Expression,
count: Expression,
bin: Expression,
ctx: &[CdtContext],
) -> Expression {
let args = vec![
ExpressionArgument::Value(Value::from(CdtListOpType::RemoveByIndexRange as i64)),
ExpressionArgument::Value(Value::from(return_type.to_bitmask())),
ExpressionArgument::FilterExpression(index),
ExpressionArgument::FilterExpression(count),
ExpressionArgument::Context(ctx.to_vec()),
];
add_write(bin, ctx, args)
}
pub fn remove_by_rank<TLR: ToListReturnTypeBitmask>(
return_type: TLR,
rank: Expression,
bin: Expression,
ctx: &[CdtContext],
) -> Expression {
let args = vec![
ExpressionArgument::Value(Value::from(CdtListOpType::RemoveByRank as i64)),
ExpressionArgument::Value(Value::from(return_type.to_bitmask())),
ExpressionArgument::FilterExpression(rank),
ExpressionArgument::Context(ctx.to_vec()),
];
add_write(bin, ctx, args)
}
pub fn remove_by_rank_range<TLR: ToListReturnTypeBitmask>(
return_type: TLR,
rank: Expression,
bin: Expression,
ctx: &[CdtContext],
) -> Expression {
let args = vec![
ExpressionArgument::Value(Value::from(CdtListOpType::RemoveByRankRange as i64)),
ExpressionArgument::Value(Value::from(return_type.to_bitmask())),
ExpressionArgument::FilterExpression(rank),
ExpressionArgument::Context(ctx.to_vec()),
];
add_write(bin, ctx, args)
}
pub fn remove_by_rank_range_count<TLR: ToListReturnTypeBitmask>(
return_type: TLR,
rank: Expression,
count: Expression,
bin: Expression,
ctx: &[CdtContext],
) -> Expression {
let args = vec![
ExpressionArgument::Value(Value::from(CdtListOpType::RemoveByRankRange as i64)),
ExpressionArgument::Value(Value::from(return_type.to_bitmask())),
ExpressionArgument::FilterExpression(rank),
ExpressionArgument::FilterExpression(count),
ExpressionArgument::Context(ctx.to_vec()),
];
add_write(bin, ctx, args)
}
pub fn size(bin: Expression, ctx: &[CdtContext]) -> Expression {
let args = vec![
ExpressionArgument::Value(Value::from(CdtListOpType::Size as i64)),
ExpressionArgument::Context(ctx.to_vec()),
];
add_read(bin, ExpType::INT, args)
}
pub fn get_by_value<TLR: ToListReturnTypeBitmask>(
return_type: TLR,
value: Expression,
bin: Expression,
ctx: &[CdtContext],
) -> Expression {
let return_type = return_type.to_bitmask();
let args = vec![
ExpressionArgument::Value(Value::from(CdtListOpType::GetByValue as i64)),
ExpressionArgument::Value(Value::from(return_type)),
ExpressionArgument::FilterExpression(value),
ExpressionArgument::Context(ctx.to_vec()),
];
add_read(bin, get_value_type(return_type), args)
}
pub fn get_by_value_range<TLR: ToListReturnTypeBitmask>(
return_type: TLR,
value_begin: Option<Expression>,
value_end: Option<Expression>,
bin: Expression,
ctx: &[CdtContext],
) -> Expression {
let return_type = return_type.to_bitmask();
let mut args = vec![
ExpressionArgument::Context(ctx.to_vec()),
ExpressionArgument::Value(Value::from(CdtListOpType::GetByValueInterval as i64)),
ExpressionArgument::Value(Value::from(return_type)),
];
if let Some(val_beg) = value_begin {
args.push(ExpressionArgument::FilterExpression(val_beg));
} else {
args.push(ExpressionArgument::FilterExpression(nil()));
}
if let Some(val_end) = value_end {
args.push(ExpressionArgument::FilterExpression(val_end));
}
add_read(bin, get_value_type(return_type), args)
}
pub fn get_by_value_list<TLR: ToListReturnTypeBitmask>(
return_type: TLR,
values: Expression,
bin: Expression,
ctx: &[CdtContext],
) -> Expression {
let return_type = return_type.to_bitmask();
let args = vec![
ExpressionArgument::Value(Value::from(CdtListOpType::GetByValueList as i64)),
ExpressionArgument::Value(Value::from(return_type)),
ExpressionArgument::FilterExpression(values),
ExpressionArgument::Context(ctx.to_vec()),
];
add_read(bin, get_value_type(return_type), args)
}
pub fn get_by_value_relative_rank_range<TLR: ToListReturnTypeBitmask>(
return_type: TLR,
value: Expression,
rank: Expression,
bin: Expression,
ctx: &[CdtContext],
) -> Expression {
let return_type = return_type.to_bitmask();
let args = vec![
ExpressionArgument::Value(Value::from(CdtListOpType::GetByValueRelRankRange as i64)),
ExpressionArgument::Value(Value::from(return_type)),
ExpressionArgument::FilterExpression(value),
ExpressionArgument::FilterExpression(rank),
ExpressionArgument::Context(ctx.to_vec()),
];
add_read(bin, get_value_type(return_type), args)
}
pub fn get_by_value_relative_rank_range_count<TLR: ToListReturnTypeBitmask>(
return_type: TLR,
value: Expression,
rank: Expression,
count: Expression,
bin: Expression,
ctx: &[CdtContext],
) -> Expression {
let return_type = return_type.to_bitmask();
let args = vec![
ExpressionArgument::Value(Value::from(CdtListOpType::GetByValueRelRankRange as i64)),
ExpressionArgument::Value(Value::from(return_type)),
ExpressionArgument::FilterExpression(value),
ExpressionArgument::FilterExpression(rank),
ExpressionArgument::FilterExpression(count),
ExpressionArgument::Context(ctx.to_vec()),
];
add_read(bin, get_value_type(return_type), args)
}
pub fn get_by_index<TLR: ToListReturnTypeBitmask>(
return_type: TLR,
value_type: ExpType,
index: Expression,
bin: Expression,
ctx: &[CdtContext],
) -> Expression {
let return_type = return_type.to_bitmask();
let args = vec![
ExpressionArgument::Value(Value::from(CdtListOpType::GetByIndex as i64)),
ExpressionArgument::Value(Value::from(return_type)),
ExpressionArgument::FilterExpression(index),
ExpressionArgument::Context(ctx.to_vec()),
];
add_read(bin, value_type, args)
}
pub fn get_by_index_range<TLR: ToListReturnTypeBitmask>(
return_type: TLR,
index: Expression,
bin: Expression,
ctx: &[CdtContext],
) -> Expression {
let return_type = return_type.to_bitmask();
let args = vec![
ExpressionArgument::Value(Value::from(CdtListOpType::GetByIndexRange as i64)),
ExpressionArgument::Value(Value::from(return_type)),
ExpressionArgument::FilterExpression(index),
ExpressionArgument::Context(ctx.to_vec()),
];
add_read(bin, get_value_type(return_type), args)
}
pub fn get_by_index_range_count<TLR: ToListReturnTypeBitmask>(
return_type: TLR,
index: Expression,
count: Expression,
bin: Expression,
ctx: &[CdtContext],
) -> Expression {
let return_type = return_type.to_bitmask();
let args = vec![
ExpressionArgument::Value(Value::from(CdtListOpType::GetByIndexRange as i64)),
ExpressionArgument::Value(Value::from(return_type)),
ExpressionArgument::FilterExpression(index),
ExpressionArgument::FilterExpression(count),
ExpressionArgument::Context(ctx.to_vec()),
];
add_read(bin, get_value_type(return_type), args)
}
pub fn get_by_rank<TLR: ToListReturnTypeBitmask>(
return_type: TLR,
value_type: ExpType,
rank: Expression,
bin: Expression,
ctx: &[CdtContext],
) -> Expression {
let return_type = return_type.to_bitmask();
let args = vec![
ExpressionArgument::Value(Value::from(CdtListOpType::GetByRank as i64)),
ExpressionArgument::Value(Value::from(return_type)),
ExpressionArgument::FilterExpression(rank),
ExpressionArgument::Context(ctx.to_vec()),
];
add_read(bin, value_type, args)
}
pub fn get_by_rank_range<TLR: ToListReturnTypeBitmask>(
return_type: TLR,
rank: Expression,
bin: Expression,
ctx: &[CdtContext],
) -> Expression {
let return_type = return_type.to_bitmask();
let args = vec![
ExpressionArgument::Value(Value::from(CdtListOpType::GetByRankRange as i64)),
ExpressionArgument::Value(Value::from(return_type)),
ExpressionArgument::FilterExpression(rank),
ExpressionArgument::Context(ctx.to_vec()),
];
add_read(bin, get_value_type(return_type), args)
}
pub fn get_by_rank_range_count<TLR: ToListReturnTypeBitmask>(
return_type: TLR,
rank: Expression,
count: Expression,
bin: Expression,
ctx: &[CdtContext],
) -> Expression {
let return_type = return_type.to_bitmask();
let args = vec![
ExpressionArgument::Value(Value::from(CdtListOpType::GetByRankRange as i64)),
ExpressionArgument::Value(Value::from(return_type)),
ExpressionArgument::FilterExpression(rank),
ExpressionArgument::FilterExpression(count),
ExpressionArgument::Context(ctx.to_vec()),
];
add_read(bin, get_value_type(return_type), args)
}
pub(crate) fn add_read(
bin: Expression,
return_type: ExpType,
arguments: Vec<ExpressionArgument>,
) -> Expression {
Expression {
cmd: Some(ExpOp::Call),
val: None,
bin: Some(Box::new(bin)),
flags: Some(MODULE),
module: Some(return_type),
exps: None,
arguments: Some(arguments),
bytes: None,
}
}
pub(crate) fn add_write(
bin: Expression,
ctx: &[CdtContext],
arguments: Vec<ExpressionArgument>,
) -> Expression {
let return_type: ExpType;
if ctx.is_empty() {
return_type = ExpType::LIST;
} else if (ctx[0].id & CtxType::ListIndex as u8) == 0 {
return_type = ExpType::MAP;
} else {
return_type = ExpType::LIST;
}
Expression {
cmd: Some(ExpOp::Call),
val: None,
bin: Some(Box::new(bin)),
flags: Some(MODULE | MODIFY),
module: Some(return_type),
exps: None,
arguments: Some(arguments),
bytes: None,
}
}
pub(crate) fn get_value_type(return_type: i64) -> ExpType {
let t = return_type & !(ListReturnType::Inverted as i64);
match t {
t if t == ListReturnType::Index as i64
|| t == ListReturnType::ReverseIndex as i64
|| t == ListReturnType::Rank as i64
|| t == ListReturnType::ReverseRank as i64 =>
{
ExpType::LIST
}
t if t == ListReturnType::Count as i64 => ExpType::INT,
t if t == ListReturnType::Values as i64 => ExpType::LIST,
t if t == ListReturnType::Exists as i64 => ExpType::BOOL,
_ => panic!("Invalid ListReturnType: {}", return_type),
}
}