use std::sync::Arc;
use crate::msgpack::encoder::pack_cdt_bit_op;
use crate::operations::cdt::{CdtArgument, CdtOperation};
use crate::operations::cdt_context::DEFAULT_CTX;
use crate::operations::{Operation, OperationBin, OperationData, OperationType};
use crate::Value;
#[derive(Debug, Clone, Copy)]
pub(crate) enum CdtBitwiseOpType {
Resize = 0,
Insert = 1,
Remove = 2,
Set = 3,
Or = 4,
Xor = 5,
And = 6,
Not = 7,
LShift = 8,
RShift = 9,
Add = 10,
Subtract = 11,
SetInt = 12,
Get = 50,
Count = 51,
LScan = 52,
RScan = 53,
GetInt = 54,
}
#[derive(Debug, Clone)]
pub enum BitwiseResizeFlags {
Default = 0,
FromFront = 1,
GrowOnly = 2,
ShrinkOnly = 4,
}
#[derive(Debug, Clone)]
pub enum BitwiseWriteFlags {
Default = 0,
CreateOnly = 1,
UpdateOnly = 2,
NoFail = 4,
Partial = 8,
}
#[derive(Debug, Clone)]
pub enum BitwiseOverflowActions {
Fail = 0,
Saturate = 2,
Wrap = 4,
}
#[derive(Debug, Clone, Copy)]
pub struct BitPolicy {
pub flags: u8,
}
impl BitPolicy {
pub const fn new(flags: u8) -> Self {
BitPolicy { flags }
}
}
impl Default for BitPolicy {
fn default() -> Self {
BitPolicy::new(BitwiseWriteFlags::Default as u8)
}
}
pub fn resize(
bin: &str,
byte_size: i64,
resize_flags: Option<BitwiseResizeFlags>,
policy: &BitPolicy,
) -> Operation {
let mut args = vec![CdtArgument::Int(byte_size), CdtArgument::Byte(policy.flags)];
if let Some(resize_flags) = resize_flags {
args.push(CdtArgument::Byte(resize_flags as u8));
}
let cdt_op = CdtOperation {
op: CdtBitwiseOpType::Resize as u8,
encoder: Arc::new(pack_cdt_bit_op),
args,
};
Operation {
op: OperationType::BitWrite,
ctx: DEFAULT_CTX,
bin: OperationBin::Name(bin.into()),
data: OperationData::CdtBitOp(cdt_op),
}
}
pub fn insert(bin: &str, byte_offset: i64, value: Value, policy: &BitPolicy) -> Operation {
let cdt_op = CdtOperation {
op: CdtBitwiseOpType::Insert as u8,
encoder: Arc::new(pack_cdt_bit_op),
args: vec![
CdtArgument::Int(byte_offset),
CdtArgument::Value(value),
CdtArgument::Byte(policy.flags),
],
};
Operation {
op: OperationType::BitWrite,
ctx: DEFAULT_CTX,
bin: OperationBin::Name(bin.into()),
data: OperationData::CdtBitOp(cdt_op),
}
}
pub fn remove(bin: &str, byte_offset: i64, byte_size: i64, policy: &BitPolicy) -> Operation {
let cdt_op = CdtOperation {
op: CdtBitwiseOpType::Remove as u8,
encoder: Arc::new(pack_cdt_bit_op),
args: vec![
CdtArgument::Int(byte_offset),
CdtArgument::Int(byte_size),
CdtArgument::Byte(policy.flags),
],
};
Operation {
op: OperationType::BitWrite,
ctx: DEFAULT_CTX,
bin: OperationBin::Name(bin.into()),
data: OperationData::CdtBitOp(cdt_op),
}
}
pub fn set(
bin: &str,
bit_offset: i64,
bit_size: i64,
value: Value,
policy: &BitPolicy,
) -> Operation {
let cdt_op = CdtOperation {
op: CdtBitwiseOpType::Set as u8,
encoder: Arc::new(pack_cdt_bit_op),
args: vec![
CdtArgument::Int(bit_offset),
CdtArgument::Int(bit_size),
CdtArgument::Value(value),
CdtArgument::Byte(policy.flags),
],
};
Operation {
op: OperationType::BitWrite,
ctx: DEFAULT_CTX,
bin: OperationBin::Name(bin.into()),
data: OperationData::CdtBitOp(cdt_op),
}
}
pub fn or(
bin: &str,
bit_offset: i64,
bit_size: i64,
value: Value,
policy: &BitPolicy,
) -> Operation {
let cdt_op = CdtOperation {
op: CdtBitwiseOpType::Or as u8,
encoder: Arc::new(pack_cdt_bit_op),
args: vec![
CdtArgument::Int(bit_offset),
CdtArgument::Int(bit_size),
CdtArgument::Value(value),
CdtArgument::Byte(policy.flags),
],
};
Operation {
op: OperationType::BitWrite,
ctx: DEFAULT_CTX,
bin: OperationBin::Name(bin.into()),
data: OperationData::CdtBitOp(cdt_op),
}
}
pub fn xor(
bin: &str,
bit_offset: i64,
bit_size: i64,
value: Value,
policy: &BitPolicy,
) -> Operation {
let cdt_op = CdtOperation {
op: CdtBitwiseOpType::Xor as u8,
encoder: Arc::new(pack_cdt_bit_op),
args: vec![
CdtArgument::Int(bit_offset),
CdtArgument::Int(bit_size),
CdtArgument::Value(value),
CdtArgument::Byte(policy.flags),
],
};
Operation {
op: OperationType::BitWrite,
ctx: DEFAULT_CTX,
bin: OperationBin::Name(bin.into()),
data: OperationData::CdtBitOp(cdt_op),
}
}
pub fn and(
bin: &str,
bit_offset: i64,
bit_size: i64,
value: Value,
policy: &BitPolicy,
) -> Operation {
let cdt_op = CdtOperation {
op: CdtBitwiseOpType::And as u8,
encoder: Arc::new(pack_cdt_bit_op),
args: vec![
CdtArgument::Int(bit_offset),
CdtArgument::Int(bit_size),
CdtArgument::Value(value),
CdtArgument::Byte(policy.flags),
],
};
Operation {
op: OperationType::BitWrite,
ctx: DEFAULT_CTX,
bin: OperationBin::Name(bin.into()),
data: OperationData::CdtBitOp(cdt_op),
}
}
pub fn not(bin: &str, bit_offset: i64, bit_size: i64, policy: &BitPolicy) -> Operation {
let cdt_op = CdtOperation {
op: CdtBitwiseOpType::Not as u8,
encoder: Arc::new(pack_cdt_bit_op),
args: vec![
CdtArgument::Int(bit_offset),
CdtArgument::Int(bit_size),
CdtArgument::Byte(policy.flags),
],
};
Operation {
op: OperationType::BitWrite,
ctx: DEFAULT_CTX,
bin: OperationBin::Name(bin.into()),
data: OperationData::CdtBitOp(cdt_op),
}
}
pub fn lshift(
bin: &str,
bit_offset: i64,
bit_size: i64,
shift: i64,
policy: &BitPolicy,
) -> Operation {
let cdt_op = CdtOperation {
op: CdtBitwiseOpType::LShift as u8,
encoder: Arc::new(pack_cdt_bit_op),
args: vec![
CdtArgument::Int(bit_offset),
CdtArgument::Int(bit_size),
CdtArgument::Int(shift),
CdtArgument::Byte(policy.flags),
],
};
Operation {
op: OperationType::BitWrite,
ctx: DEFAULT_CTX,
bin: OperationBin::Name(bin.into()),
data: OperationData::CdtBitOp(cdt_op),
}
}
pub fn rshift(
bin: &str,
bit_offset: i64,
bit_size: i64,
shift: i64,
policy: &BitPolicy,
) -> Operation {
let cdt_op = CdtOperation {
encoder: Arc::new(pack_cdt_bit_op),
op: CdtBitwiseOpType::RShift as u8,
args: vec![
CdtArgument::Int(bit_offset),
CdtArgument::Int(bit_size),
CdtArgument::Int(shift),
CdtArgument::Byte(policy.flags),
],
};
Operation {
op: OperationType::BitWrite,
ctx: DEFAULT_CTX,
bin: OperationBin::Name(bin.into()),
data: OperationData::CdtBitOp(cdt_op),
}
}
pub fn add(
bin: &str,
bit_offset: i64,
bit_size: i64,
value: i64,
signed: bool,
action: BitwiseOverflowActions,
policy: &BitPolicy,
) -> Operation {
let mut action_flags = action as u8;
if signed {
action_flags |= 1;
}
let cdt_op = CdtOperation {
op: CdtBitwiseOpType::Add as u8,
encoder: Arc::new(pack_cdt_bit_op),
args: vec![
CdtArgument::Int(bit_offset),
CdtArgument::Int(bit_size),
CdtArgument::Int(value),
CdtArgument::Byte(policy.flags),
CdtArgument::Byte(action_flags),
],
};
Operation {
op: OperationType::BitWrite,
ctx: DEFAULT_CTX,
bin: OperationBin::Name(bin.into()),
data: OperationData::CdtBitOp(cdt_op),
}
}
pub fn subtract(
bin: &str,
bit_offset: i64,
bit_size: i64,
value: i64,
signed: bool,
action: BitwiseOverflowActions,
policy: &BitPolicy,
) -> Operation {
let mut action_flags = action as u8;
if signed {
action_flags |= 1;
}
let cdt_op = CdtOperation {
op: CdtBitwiseOpType::Subtract as u8,
encoder: Arc::new(pack_cdt_bit_op),
args: vec![
CdtArgument::Int(bit_offset),
CdtArgument::Int(bit_size),
CdtArgument::Int(value),
CdtArgument::Byte(policy.flags),
CdtArgument::Byte(action_flags),
],
};
Operation {
op: OperationType::BitWrite,
ctx: DEFAULT_CTX,
bin: OperationBin::Name(bin.into()),
data: OperationData::CdtBitOp(cdt_op),
}
}
pub fn set_int(
bin: &str,
bit_offset: i64,
bit_size: i64,
value: i64,
policy: &BitPolicy,
) -> Operation {
let cdt_op = CdtOperation {
op: CdtBitwiseOpType::SetInt as u8,
encoder: Arc::new(pack_cdt_bit_op),
args: vec![
CdtArgument::Int(bit_offset),
CdtArgument::Int(bit_size),
CdtArgument::Int(value),
CdtArgument::Byte(policy.flags),
],
};
Operation {
op: OperationType::BitWrite,
ctx: DEFAULT_CTX,
bin: OperationBin::Name(bin.into()),
data: OperationData::CdtBitOp(cdt_op),
}
}
pub fn get(bin: &str, bit_offset: i64, bit_size: i64) -> Operation {
let cdt_op = CdtOperation {
op: CdtBitwiseOpType::Get as u8,
encoder: Arc::new(pack_cdt_bit_op),
args: vec![CdtArgument::Int(bit_offset), CdtArgument::Int(bit_size)],
};
Operation {
op: OperationType::BitRead,
ctx: DEFAULT_CTX,
bin: OperationBin::Name(bin.into()),
data: OperationData::CdtBitOp(cdt_op),
}
}
pub fn count(bin: &str, bit_offset: i64, bit_size: i64) -> Operation {
let cdt_op = CdtOperation {
op: CdtBitwiseOpType::Count as u8,
encoder: Arc::new(pack_cdt_bit_op),
args: vec![CdtArgument::Int(bit_offset), CdtArgument::Int(bit_size)],
};
Operation {
op: OperationType::BitRead,
ctx: DEFAULT_CTX,
bin: OperationBin::Name(bin.into()),
data: OperationData::CdtBitOp(cdt_op),
}
}
pub fn lscan(bin: &str, bit_offset: i64, bit_size: i64, value: bool) -> Operation {
let cdt_op = CdtOperation {
op: CdtBitwiseOpType::LScan as u8,
encoder: Arc::new(pack_cdt_bit_op),
args: vec![
CdtArgument::Int(bit_offset),
CdtArgument::Int(bit_size),
CdtArgument::Bool(value),
],
};
Operation {
op: OperationType::BitRead,
ctx: DEFAULT_CTX,
bin: OperationBin::Name(bin.into()),
data: OperationData::CdtBitOp(cdt_op),
}
}
pub fn rscan(bin: &str, bit_offset: i64, bit_size: i64, value: bool) -> Operation {
let cdt_op = CdtOperation {
op: CdtBitwiseOpType::RScan as u8,
encoder: Arc::new(pack_cdt_bit_op),
args: vec![
CdtArgument::Int(bit_offset),
CdtArgument::Int(bit_size),
CdtArgument::Bool(value),
],
};
Operation {
op: OperationType::BitRead,
ctx: DEFAULT_CTX,
bin: OperationBin::Name(bin.into()),
data: OperationData::CdtBitOp(cdt_op),
}
}
pub fn get_int(bin: &str, bit_offset: i64, bit_size: i64, signed: bool) -> Operation {
let mut args = vec![CdtArgument::Int(bit_offset), CdtArgument::Int(bit_size)];
if signed {
args.push(CdtArgument::Byte(1));
}
let cdt_op = CdtOperation {
op: CdtBitwiseOpType::GetInt as u8,
encoder: Arc::new(pack_cdt_bit_op),
args,
};
Operation {
op: OperationType::BitRead,
ctx: DEFAULT_CTX,
bin: OperationBin::Name(bin.into()),
data: OperationData::CdtBitOp(cdt_op),
}
}