Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Node: fix BITPOS #2227

Merged
merged 18 commits into from
Dec 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@
* Node: Replace instances of Redis with Valkey ([#2260](https://github.com/valkey-io/valkey-glide/pull/2260))
* Node: Added binary variant for commands which have `Record` as input or output ([#2207](https://github.com/valkey-io/valkey-glide/pull/2207))
* Node: Renamed `ReturnType` to `GlideReturnType` ([#2241](https://github.com/valkey-io/valkey-glide/pull/2241))
* Node: Fix BITPOS for Valkey8 ([#2227](https://github.com/valkey-io/valkey-glide/pull/2227))
* Node, Python: Rename `stop` to `end` in sorted set queries ([#2214](https://github.com/valkey-io/valkey-glide/pull/2214))
* Node: Added binary variant to sorted set commands - part 1 ([#2190](https://github.com/valkey-io/valkey-glide/pull/2190))
* Node: Added binary variant to HSCAN command ([#2240](https://github.com/valkey-io/valkey-glide/pull/2240))
Expand Down
62 changes: 12 additions & 50 deletions node/src/BaseClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import {
BitOffset, // eslint-disable-line @typescript-eslint/no-unused-vars
BitOffsetMultiplier, // eslint-disable-line @typescript-eslint/no-unused-vars
BitOffsetOptions,
BitmapIndexType,
BitwiseOperation,
Boundary,
CoordOrigin, // eslint-disable-line @typescript-eslint/no-unused-vars
Expand Down Expand Up @@ -1874,11 +1873,12 @@ export class BaseClient {
* The offset can also be a negative number indicating an offset starting at the end of the list, with `-1` being
* the last byte of the list, `-2` being the penultimate, and so on.
*
* @see {@link https://valkey.io/commands/bitpos/|valkey.io} for more details.
* @see {@link https://valkey.io/commands/bitpos/|valkey.io} for details.
*
* @param key - The key of the string.
* @param bit - The bit value to match. Must be `0` or `1`.
* @param start - (Optional) The starting offset. If not supplied, the search will start at the beginning of the string.
* @param options - (Optional) The {@link BitOffsetOptions}.
*
* @returns The position of the first occurrence of `bit` in the binary value of the string held at `key`.
* If `start` was provided, the search begins at the offset indicated by `start`.
*
Expand All @@ -1888,61 +1888,23 @@ export class BaseClient {
* const result1 = await client.bitpos("key1", 1);
* console.log(result1); // Output: 1 - The first occurrence of bit value 1 in the string stored at "key1" is at the second position.
*
* const result2 = await client.bitpos("key1", 1, -1);
* const result2 = await client.bitpos("key1", 1, { start: -1 });
* console.log(result2); // Output: 10 - The first occurrence of bit value 1, starting at the last byte in the string stored at "key1", is at the eleventh position.
* ```
*/
public async bitpos(
key: GlideString,
bit: number,
start?: number,
): Promise<number> {
return this.createWritePromise(createBitPos(key, bit, start));
}

/**
* Returns the position of the first bit matching the given `bit` value. The offsets are zero-based indexes, with
* `0` being the first element of the list, `1` being the next, and so on. These offsets can also be negative
* numbers indicating offsets starting at the end of the list, with `-1` being the last element of the list, `-2`
* being the penultimate, and so on.
*
* If you are using Valkey 7.0.0 or above, the optional `indexType` can also be provided to specify whether the
* `start` and `end` offsets specify BIT or BYTE offsets. If `indexType` is not provided, BYTE offsets
* are assumed. If BIT is specified, `start=0` and `end=2` means to look at the first three bits. If BYTE is
* specified, `start=0` and `end=2` means to look at the first three bytes.
*
* @see {@link https://valkey.io/commands/bitpos/|valkey.io} for more details.
*
* @param key - The key of the string.
* @param bit - The bit value to match. Must be `0` or `1`.
* @param start - The starting offset.
* @param end - The ending offset.
* @param indexType - (Optional) The index offset type. This option can only be specified if you are using Valkey
* version 7.0.0 or above. Could be either {@link BitmapIndexType.BYTE} or {@link BitmapIndexType.BIT}. If no
* index type is provided, the indexes will be assumed to be byte indexes.
* @returns The position of the first occurrence from the `start` to the `end` offsets of the `bit` in the binary
* value of the string held at `key`.
*
* @example
* ```typescript
* await client.set("key1", "A12"); // "A12" has binary value 01000001 00110001 00110010
* const result1 = await client.bitposInterval("key1", 1, 1, -1);
* console.log(result1); // Output: 10 - The first occurrence of bit value 1 in the second byte to the last byte of the string stored at "key1" is at the eleventh position.
* const result3 = await client.bitpos("key1", 1, { start: 1, end: -1 });
* console.log(result3); // Output: 10 - The first occurrence of bit value 1 in the second byte to the last byte of the string stored at "key1" is at the eleventh position.
*
* const result2 = await client.bitposInterval("key1", 1, 2, 9, BitmapIndexType.BIT);
* console.log(result2); // Output: 7 - The first occurrence of bit value 1 in the third to tenth bits of the string stored at "key1" is at the eighth position.
* const result4 = await client.bitpos("key1", 1, { start: 2, end: 9, indexType: BitmapIndexType.BIT });
* console.log(result4); // Output: 7 - The first occurrence of bit value 1 in the third to tenth bits of the string stored at "key1" is at the eighth position.
* ```
*/
public async bitposInterval(
public async bitpos(
key: GlideString,
bit: number,
start: number,
end: number,
indexType?: BitmapIndexType,
options?: BitOffsetOptions,
): Promise<number> {
return this.createWritePromise(
createBitPos(key, bit, start, end, indexType),
);
return this.createWritePromise(createBitPos(key, bit, options));
}

/**
Expand Down Expand Up @@ -6577,7 +6539,7 @@ export class BaseClient {
* @see {@link https://valkey.io/commands/bitcount/|valkey.io} for more details.
*
* @param key - The key for the string to count the set bits of.
* @param options - The offset options.
* @param options - The offset options - see {@link BitOffsetOptions}.
* @returns If `options` is provided, returns the number of set bits in the string interval specified by `options`.
* If `options` is not provided, returns the number of set bits in the string stored at `key`.
* Otherwise, if `key` is missing, returns `0` as it is treated as an empty string.
Expand Down
65 changes: 40 additions & 25 deletions node/src/Commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2475,18 +2475,25 @@ export function createFunctionRestore(
}

/**
* Represents offsets specifying a string interval to analyze in the {@link BaseClient.bitcount|bitcount} command. The offsets are
* zero-based indexes, with `0` being the first index of the string, `1` being the next index and so on.
* Represents offsets specifying a string interval to analyze in the {@link BaseClient.bitcount | bitcount} and {@link BaseClient.bitpos | bitpos} commands.
* The offsets are zero-based indexes, with `0` being the first index of the string, `1` being the next index and so on.
* The offsets can also be negative numbers indicating offsets starting at the end of the string, with `-1` being
* the last index of the string, `-2` being the penultimate, and so on.
*
* See https://valkey.io/commands/bitcount/ for more details.
* If you are using Valkey 7.0.0 or above, the optional `indexType` can also be provided to specify whether the
* `start` and `end` offsets specify `BIT` or `BYTE` offsets. If `indexType` is not provided, `BYTE` offsets
* are assumed. If `BIT` is specified, `start=0` and `end=2` means to look at the first three bits. If `BYTE` is
* specified, `start=0` and `end=2` means to look at the first three bytes.
*
* @see {@link https://valkey.io/commands/bitcount/ | bitcount} and {@link https://valkey.io/commands/bitpos/ | bitpos} for more details.
*/
export interface BitOffsetOptions {
/** The starting offset index. */
start: number;
/** The ending offset index. Optional since Valkey version 8.0 and above.
* If not provided, it will default to the end of the string
/**
* The ending offset index. Optional since Valkey version 8.0 and above for the BITCOUNT command.
* If not provided, it will default to the end of the string.
* Could be defined only if `start` is defined.
*/
end?: number;
/**
Expand All @@ -2497,19 +2504,36 @@ export interface BitOffsetOptions {
indexType?: BitmapIndexType;
}

/**
* @internal
*/
function convertBitOptionsToArgs(options?: BitOffsetOptions): GlideString[] {
const args: GlideString[] = [];
if (!options) return args;

args.push(options.start.toString());

if (options.end !== undefined) {
args.push(options.end.toString());

if (options.indexType) args.push(options.indexType);
}

return args;
}

/**
* @internal
*/
export function createBitCount(
key: GlideString,
options?: BitOffsetOptions,
): command_request.Command {
const args = [key];
let args: GlideString[] = [key];

if (options) {
args.push(options.start.toString());
if (options.end !== undefined) args.push(options.end.toString());
if (options.indexType) args.push(options.indexType);
const optionResults: GlideString[] = convertBitOptionsToArgs(options);
args = args.concat(optionResults);
}

return createCommand(RequestType.BitCount, args);
Expand All @@ -2525,6 +2549,7 @@ export function createBitCount(
export enum BitmapIndexType {
/** Specifies that provided indexes are byte indexes. */
BYTE = "BYTE",

/** Specifies that provided indexes are bit indexes. */
BIT = "BIT",
}
Expand All @@ -2535,23 +2560,13 @@ export enum BitmapIndexType {
export function createBitPos(
key: GlideString,
bit: number,
start?: number,
end?: number,
indexType?: BitmapIndexType,
options?: BitOffsetOptions,
): command_request.Command {
const args: GlideString[] = [key, bit.toString()];

if (start !== undefined) {
args.push(start.toString());
}

if (end !== undefined) {
args.push(end.toString());
}

if (indexType) {
args.push(indexType);
}
const args: GlideString[] = [
key,
bit.toString(),
...convertBitOptionsToArgs(options),
];

return createCommand(RequestType.BitPos, args);
}
Expand Down
41 changes: 5 additions & 36 deletions node/src/Transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import {
BitOffset, // eslint-disable-line @typescript-eslint/no-unused-vars
BitOffsetMultiplier, // eslint-disable-line @typescript-eslint/no-unused-vars
BitOffsetOptions,
BitmapIndexType,
BitwiseOperation,
Boundary,
CoordOrigin, // eslint-disable-line @typescript-eslint/no-unused-vars
Expand Down Expand Up @@ -686,47 +685,17 @@ export class BaseTransaction<T extends BaseTransaction<T>> {
*
* @param key - The key of the string.
* @param bit - The bit value to match. Must be `0` or `1`.
* @param start - (Optional) The starting offset. If not supplied, the search will start at the beginning of the string.
* @param options - (Optional) The {@link BitOffsetOptions}.
*
* Command Response - The position of the first occurrence of `bit` in the binary value of the string held at `key`.
* If `start` was provided, the search begins at the offset indicated by `start`.
*/
public bitpos(key: GlideString, bit: number, start?: number): T {
return this.addAndReturn(createBitPos(key, bit, start));
}

/**
* Returns the position of the first bit matching the given `bit` value. The offsets are zero-based indexes, with
* `0` being the first element of the list, `1` being the next, and so on. These offsets can also be negative
* numbers indicating offsets starting at the end of the list, with `-1` being the last element of the list, `-2`
* being the penultimate, and so on.
*
* If you are using Valkey 7.0.0 or above, the optional `indexType` can also be provided to specify whether the
* `start` and `end` offsets specify BIT or BYTE offsets. If `indexType` is not provided, BYTE offsets
* are assumed. If BIT is specified, `start=0` and `end=2` means to look at the first three bits. If BYTE is
* specified, `start=0` and `end=2` means to look at the first three bytes.
*
* @see {@link https://valkey.io/commands/bitpos/|valkey.io} for details.
*
* @param key - The key of the string.
* @param bit - The bit value to match. Must be `0` or `1`.
* @param start - The starting offset.
* @param end - The ending offset.
* @param indexType - (Optional) The index offset type. This option can only be specified if you are using Valkey
* version 7.0.0 or above. Could be either {@link BitmapIndexType.BYTE} or {@link BitmapIndexType.BIT}. If no
* index type is provided, the indexes will be assumed to be byte indexes.
*
* Command Response - The position of the first occurrence from the `start` to the `end` offsets of the `bit` in the
* binary value of the string held at `key`.
*/
public bitposInterval(
public bitpos(
key: GlideString,
bit: number,
start: number,
end: number,
indexType?: BitmapIndexType,
options?: BitOffsetOptions,
): T {
return this.addAndReturn(createBitPos(key, bit, start, end, indexType));
return this.addAndReturn(createBitPos(key, bit, options));
}

/**
Expand Down Expand Up @@ -3516,7 +3485,7 @@ export class BaseTransaction<T extends BaseTransaction<T>> {
* @see {@link https://valkey.io/commands/bitcount/|valkey.io} for more details.
*
* @param key - The key for the string to count the set bits of.
* @param options - The offset options.
* @param options - The offset options - see {@link BitOffsetOptions}.
*
* Command Response - If `options` is provided, returns the number of set bits in the string interval specified by `options`.
* If `options` is not provided, returns the number of set bits in the string stored at `key`.
Expand Down
Loading
Loading