// *****************************************************************************
// Copyright 2022-2023 Aerospike, Inc.
//
// Licensed under the Apache License, Version 2.0 (the 'License')
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an 'AS IS' BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// *****************************************************************************
const as = require('bindings')('aerospike.node')
const exp = as.exp
const bits = as.bitwise
const _valueExp = (op, valName) => (value) => [{ op, [valName]: value }]
const _uint = _valueExp(exp.ops.VAL_UINT, 'uintVal')
const _int = _valueExp(exp.ops.VAL_INT, 'intVal')
const _rtype = _valueExp(exp.ops.VAL_RTYPE, 'intVal')
/*********************************************************************************
* BIT MODIFY EXPRESSIONS
*********************************************************************************/
const _bitModify = () => [
{ op: exp.ops.CALL, count: 5 },
..._rtype(exp.type.BLOB),
..._int(exp.sys.CALL_BITS | exp.sys.FLAG_MODIFY_LOCAL)
]
const _bitModStart = (op, param) => [
..._bitModify(),
{ op: exp.ops.CALL_VOP_START, count: 1 + param },
..._int(op)
]
const _bitRead = (returnType) => [
{ op: exp.ops.CALL, count: 5 },
..._rtype(returnType),
..._int(exp.sys.CALL_BITS)
]
const _bitReadStart = (returnType, op, param) => [
..._bitRead(returnType),
{ op: exp.ops.CALL_VOP_START, count: 1 + param },
..._int(op)
]
/**
* @module aerospike/exp/bit
*
* @description The {@link module:aerospike/exp/bit|aerospike/exp/bit} module defines functions
* for expressions on the Blob datatype.
*/
module.exports = {
/**
* Create an expression that performs bit resize operation.
*
* @param {Object} policy bit policy value.
* @param {number} byteSize Number of bytes the resulting blob should occupy.
* @param {number} flags bit resize flags value.
* @param {AerospikeExp} bin A blob bin expression to apply this function to.
* @return {AerospikeExp} blob bin byteSize bytes.
*/
reSize: (bin, flags, byteSize, policy = null) => [
..._bitModStart(bits.opcodes.RESIZE, 3),
...byteSize,
..._uint((policy ? policy.flags : 0)),
..._uint(flags),
...bin
],
/**
* Create an expression that performs bit insert operation.
*
* @param {Object} policy bit policy value.
* @param {AerospikeExp} byteOffset Byte index of where to insert the value.
* @param {AerospikeExp} value Blob expression containing the bytes to insert.
* @param {AerospikeExp} bin A blob bin expression to apply this function to.
* @return {AerospikeExp} blob bin resulting blob containing the inserted bytes.
*/
insert: (bin, value, byteOffset, policy = null) => [
..._bitModStart(bits.opcodes.INSERT, 3),
...byteOffset,
...value,
..._uint((policy ? policy.flags : 0)),
...bin
],
/**
* Create an expression that performs bit remove operation.
*
* @param {Object} policy bit policy value.
* @param {AerospikeExp} byteOffset Byte index of where to remove from.
* @param {number} byteSize Number of bytes to remove.
* @param {AerospikeExp} bin A blob bin expression to apply this function to.
* @return {AerospikeExp} blob bin resulting blob with the bytes removed.
*/
remove: (bin, byteSize, byteOffset, policy = null) => [
..._bitModStart(bits.opcodes.REMOVE, 3),
...byteOffset,
...byteSize,
..._uint((policy ? policy.flags : 0)),
...bin
],
/**
* Create an expression that performs bit set operation.
*
* @param {Object} policy bit policy value.
* @param {AerospikeExp} bitOffset Bit index of where to start writing.
* @param {AerospikeExp} bitSize Number of bytes to overwrite.
* @param {AerospikeExp} value Blob expression containing bytes to write.
* @param {AerospikeExp} bin A blob bin expression to apply this function to.
* @return {AerospikeExp} blob bin resulting blob with the bytes overwritten.
*/
set: (bin, value, bitSize, bitOffset, policy = null) => [
..._bitModStart(bits.opcodes.SET, 4),
...bitOffset,
...bitSize,
...value,
..._uint((policy ? policy.flags : 0)),
...bin
],
/**
* Create an expression that performs bit or operation.
*
* @param {Object} policy bit policy value.
* @param {AerospikeExp} bitOffset Bit index of where to start operation.
* @param {AerospikeExp} bitSize Number of bytes to be operated on.
* @param {AerospikeExp} value Blob expression containing bytes to write.
* @param {AerospikeExp} bin A blob bin expression to apply this function to.
* @return {AerospikeExp} blob bin resulting blob with the bytes operated on.
*/
or: (bin, value, bitSize, bitOffset, policy = null) => [
..._bitModStart(bits.opcodes.OR, 4),
...bitOffset,
...bitSize,
...value,
..._uint((policy ? policy.flags : 0)),
...bin
],
/**
* Create an expression that performs bit xor operation.
*
* @param {Object} policy bit policy value.
* @param {AerospikeExp} bitOffset Bit index of where to start operation.
* @param {AerospikeExp} bitSize Number of bits to be operated on.
* @param {AerospikeExp} value Blob expression containing bytes to write.
* @param {AerospikeExp} bin A blob bin expression to apply this function to.
* @return {AerospikeExp} blob bin resulting blob with the bytes operated on.
*/
xor: (bin, value, bitSize, bitOffset, policy = null) => [
..._bitModStart(bits.opcodes.XOR, 4),
...bitOffset,
...bitSize,
...value,
..._uint((policy ? policy.flags : 0)),
...bin
],
/**
* Create an expression that performs bit and operation.
*
* @param {Object} policy bit policy value.
* @param {AerospikeExp} bitOffset Bit index of where to start operation.
* @param {AerospikeExp} bitSize Number of bits to be operated on.
* @param {AerospikeExp} value Blob expression containing bytes to write.
* @param {AerospikeExp} bin A blob bin expression to apply this function to.
* @return {AerospikeExp} blob bin resulting blob with the bytes operated on.
*/
and: (bin, value, bitSize, bitOffset, policy = null) => [
..._bitModStart(bits.opcodes.AND, 4),
...bitOffset,
...bitSize,
...value,
..._uint((policy ? policy.flags : 0)),
...bin
],
/**
* Create an expression that performs bit not operation.
*
* @param {Object} policy bit policy value.
* @param {AerospikeExp} bitOffset Bit index of where to start operation.
* @param {AerospikeExp} bitSize Number of bits to be operated on.
* @param {AerospikeExp} bin A blob bin expression to apply this function to.
* @return {AerospikeExp} blob bin resulting blob with the bytes operated on.
*/
not: (bin, bitSize, bitOffset, policy = null) => [
..._bitModStart(bits.opcodes.NOT, 3),
...bitOffset,
...bitSize,
..._uint((policy ? policy.flags : 0)),
...bin
],
/**
* Create an expression that performs an bit lshift operation.
*
* @param {Object} policy bit policy value.
* @param {AerospikeExp} bitOffset Bit index of where to start operation.
* @param {AerospikeExp} bitSize Number of bits to be operated on.
* @param {number} shift Number of bits to shift by.
* @param {AerospikeExp} bin A blob bin expression to apply this function to.
* @return {AerospikeExp} blob bin resulting blob with the bytes operated on.
*/
lShift: (bin, shift, bitSize, bitOffset, policy = null) => [
..._bitModStart(bits.opcodes.LSHIFT, 4),
...bitOffset,
...bitSize,
...shift,
..._uint((policy ? policy.flags : 0)),
...bin
],
/**
* Create an expression that performs bit rshift operation.
*
* @param {Object} policy bit policy value.
* @param {AerospikeExp} bitOffset Bit index of where to start operation.
* @param {AerospikeExp} bitSize Number of bits to be operated on.
* @param {number} shift Number of bits to shift by.
* @param {AerospikeExp} bin A blob bin expression to apply this function to.
* @return {AerospikeExp} blob bin resulting blob with the bytes operated on.
*/
rShift: (bin, shift, bitSize, bitOffset, policy = null) => [
..._bitModStart(bits.opcodes.RSHIFT, 4),
...bitOffset,
...bitSize,
...shift,
..._uint((policy ? policy.flags : 0)),
...bin
],
/**
* Create an expression that performs bit add operation.
* Note: integers are stored big-endian.
*
* @param {Object} policy bit policy value.
* @param {AerospikeExp} bitOffset Bit index of where to start operation.
* @param {AerospikeExp} bitSize Number of bits to be operated on.
* @param {AerospikeExp} value Integer expression for value to add.
* @param {number} action bit overflow action value.
* @param {AerospikeExp} bin A blob bin expression to apply this function to.
* @return {AerospikeExp} blob bin resulting blob with the bytes operated on.
*/
add: (bin, action, value, bitSize, bitOffset, policy = null) => [
..._bitModStart(bits.opcodes.ADD, 5),
...bitOffset,
...bitSize,
...value,
..._uint((policy ? policy.flags : 0)),
..._uint(action),
...bin
],
/**
* Create an expression that performs bit add operation.
* Note: integers are stored big-endian.
*
* @param {Object} policy bit policy value.
* @param {AerospikeExp} bitOffset Bit index of where to start operation.
* @param {AerospikeExp} bitSize Number of bits to be operated on.
* @param {AerospikeExp} value Integer expression for value to subtract.
* @param {number} action bit overflow action value.
* @param {AerospikeExp} bin A blob bin expression to apply this function to.
* @return {AerospikeExp} blob bin resulting blob with the bytes operated on.
*/
subtract: (bin, action, value, bitSize, bitOffset, policy = null) => [
..._bitModStart(bits.opcodes.SUBTRACT, 5),
...bitOffset,
...bitSize,
...value,
..._uint((policy ? policy.flags : 0)),
..._uint(action),
...bin
],
/**
* Create an expression that performs bit add operation.
* Note: integers are stored big-endian.
*
* @param {Object} policy bit policy value.
* @param {AerospikeExp} bitOffset Bit index of where to start operation.
* @param {AerospikeExp} bitSize Number of bits to be operated on.
* @param {AerospikeExp} value Integer expression for value to set.
* @param {AerospikeExp} bin A blob bin expression to apply this function to.
* @return {AerospikeExp} blob bin resulting blob with the bytes operated on.
*/
setInt: (bin, value, bitSize, bitOffset, policy = null) => [
..._bitModStart(bits.opcodes.SET_INT, 4),
...bitOffset,
...bitSize,
...value,
..._uint((policy ? policy.flags : 0)),
...bin
],
/*********************************************************************************
* BIT READ EXPRESSIONS
*********************************************************************************/
/**
* Create an expression that performs bit get operation.
*
* @param {AerospikeExp} bitOffset The bit index of where to start reading from.
* @param {AerospikeExp} bitSize Number of bits to read from the blob bin.
* @param {AerospikeExp} bin A blob bin expression to apply this function to.
* @return {AerospikeExp} blob bin bit_size bits rounded up to the nearest byte size.
*/
get: (bin, bitSize, bitOffset) => [
..._bitReadStart(exp.type.BLOB, bits.opcodes.GET, 2),
...bitOffset,
...bitSize,
...bin
],
/**
* Create an expression that performs bit count operation.
*
* @param {AerospikeExp} bitOffset The bit index of where to start reading from.
* @param {AerospikeExp} bitSize Number of bits to read from the blob bin.
* @param {AerospikeExp} bin A blob bin expression to apply this function to.
* @return {number} integer value number of bits set to 1 in the bit_size region.
*/
count: (bin, bitSize, bitOffset) => [
..._bitReadStart(exp.type.INT, bits.opcodes.COUNT, 2),
...bitOffset,
...bitSize,
...bin
],
/**
* Create an expression that performs bit lscan operation.
*
* @param {AerospikeExp} bitOffset The bit index of where to start reading from.
* @param {AerospikeExp} bitSize Number of bits to read from the blob bin.
* @param {AerospikeExp} value Boolean expression, true searches for 1, false for 0.
* @param {AerospikeExp} bin A blob bin expression to apply this function to.
* @return {number} integer value Index of the left most bit starting from __offset set to value.
*/
lScan: (bin, value, bitSize, bitOffset) => [
..._bitReadStart(exp.type.INT, bits.opcodes.LSCAN, 3),
...bitOffset,
...bitSize,
...value,
...bin
],
/**
* Create an expression that performs bit rscan operation.
*
* @param {AerospikeExp} bitOffset The bit index of where to start reading from.
* @param {AerospikeExp} bitSize Number of bits to read from the blob bin.
* @param {AerospikeExp} value Boolean expression, true searches for 1, false for 0.
* @param {AerospikeExp} bin A blob bin expression to apply this function to.
* @return {number} integer value Index of the right most bit starting from __offset set to value.
*/
rScan: (bin, value, bitSize, bitOffset) => [
..._bitReadStart(exp.type.INT, bits.opcodes.RSCAN, 3),
...bitOffset,
...bitSize,
...value,
...bin
],
/**
* Create an expression that performs bit get_int operation.
*
* @param {AerospikeExp} bitOffset The bit index of where to start reading from.
* @param {AerospikeExp} bitSize Number of bits to read from the blob bin.
* @param {boolean} sign Boolean value, true for signed, false for unsigned.
* @param {AerospikeExp} bin A blob bin expression to apply this function to.
* @return {AerospikeExp} integer value Index of the left most bit starting from offset set to value.
*/
getInt: (bin, sign, bitSize, bitOffset) => [
..._bitReadStart(exp.type.INT, bits.opcodes.GET_INT, 3),
...bitOffset,
...bitSize,
..._int((sign ? 1 : 0)),
...bin
]
}