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

Java: Add BITFIELD and BITFIELD_RO commands #1510

Merged
merged 8 commits into from
Jun 4, 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
2 changes: 2 additions & 0 deletions glide-core/src/protobuf/redis_request.proto
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,8 @@ enum RequestType {
BLMove = 169;
GetDel = 170;
SRandMember = 171;
BitField = 172;
BitFieldReadOnly = 173;
SInterCard = 175;
}

Expand Down
6 changes: 6 additions & 0 deletions glide-core/src/request_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,8 @@ pub enum RequestType {
BLMove = 169,
GetDel = 170,
SRandMember = 171,
BitField = 172,
BitFieldReadOnly = 173,
SInterCard = 175,
}

Expand Down Expand Up @@ -348,6 +350,8 @@ impl From<::protobuf::EnumOrUnknown<ProtobufRequestType>> for RequestType {
ProtobufRequestType::BLMove => RequestType::BLMove,
ProtobufRequestType::GetDel => RequestType::GetDel,
ProtobufRequestType::SRandMember => RequestType::SRandMember,
ProtobufRequestType::BitField => RequestType::BitField,
ProtobufRequestType::BitFieldReadOnly => RequestType::BitFieldReadOnly,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
ProtobufRequestType::BitFieldReadOnly => RequestType::BitFieldReadOnly,
ProtobufRequestType:: BitField_Ro => RequestType:: BitField_Ro,

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@acarbonetto, why?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The command is: bitfield_ro
We don't replace letters, for example: XDel. Not XDelete or StreamDelete.
What's different about the _ro?

ProtobufRequestType::SInterCard => RequestType::SInterCard,
}
}
Expand Down Expand Up @@ -520,6 +524,8 @@ impl RequestType {
RequestType::BLMove => Some(cmd("BLMOVE")),
RequestType::GetDel => Some(cmd("GETDEL")),
RequestType::SRandMember => Some(cmd("SRANDMEMBER")),
RequestType::BitField => Some(cmd("BITFIELD")),
RequestType::BitFieldReadOnly => Some(cmd("BITFIELD_RO")),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
RequestType::BitFieldReadOnly => Some(cmd("BITFIELD_RO")),
RequestType:: BitField_Ro => Some(cmd("BITFIELD_RO")),

RequestType::SInterCard => Some(cmd("SINTERCARD")),
}
}
Expand Down
23 changes: 23 additions & 0 deletions java/client/src/main/java/glide/api/BaseClient.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
/** Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0 */
package glide.api;

import static glide.api.models.commands.bitmap.BitFieldOptions.BitFieldReadOnlySubCommands;
import static glide.api.models.commands.bitmap.BitFieldOptions.BitFieldSubCommands;
import static glide.api.models.commands.bitmap.BitFieldOptions.createBitFieldArgs;
import static glide.ffi.resolvers.SocketListenerResolver.getSocket;
import static glide.utils.ArrayTransformUtils.castArray;
import static glide.utils.ArrayTransformUtils.castArrayofArrays;
Expand All @@ -18,6 +21,8 @@
import static redis_request.RedisRequestOuterClass.RequestType.BZPopMax;
import static redis_request.RedisRequestOuterClass.RequestType.BZPopMin;
import static redis_request.RedisRequestOuterClass.RequestType.BitCount;
import static redis_request.RedisRequestOuterClass.RequestType.BitField;
import static redis_request.RedisRequestOuterClass.RequestType.BitFieldReadOnly;
import static redis_request.RedisRequestOuterClass.RequestType.BitOp;
import static redis_request.RedisRequestOuterClass.RequestType.BitPos;
import static redis_request.RedisRequestOuterClass.RequestType.Decr;
Expand Down Expand Up @@ -1637,4 +1642,22 @@ public CompletableFuture<String[]> srandmember(@NonNull String key, long count)
return commandManager.submitNewCommand(
SRandMember, arguments, response -> castArray(handleArrayResponse(response), String.class));
}

@Override
public CompletableFuture<Long[]> bitfield(
@NonNull String key, @NonNull BitFieldSubCommands[] subCommands) {
String[] arguments = ArrayUtils.addFirst(createBitFieldArgs(subCommands), key);
return commandManager.submitNewCommand(
BitField, arguments, response -> castArray(handleArrayResponse(response), Long.class));
}

@Override
public CompletableFuture<Long[]> bitfieldReadOnly(
@NonNull String key, @NonNull BitFieldReadOnlySubCommands[] subCommands) {
String[] arguments = ArrayUtils.addFirst(createBitFieldArgs(subCommands), key);
return commandManager.submitNewCommand(
BitFieldReadOnly,
arguments,
response -> castArray(handleArrayResponse(response), Long.class));
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
/** Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0 */
package glide.api.commands;

import static glide.api.models.commands.bitmap.BitFieldOptions.BitFieldReadOnlySubCommands;
import static glide.api.models.commands.bitmap.BitFieldOptions.BitFieldSubCommands;

import glide.api.models.commands.bitmap.BitFieldOptions.BitFieldGet;
import glide.api.models.commands.bitmap.BitFieldOptions.BitFieldIncrby;
import glide.api.models.commands.bitmap.BitFieldOptions.BitFieldOverflow;
import glide.api.models.commands.bitmap.BitFieldOptions.BitFieldSet;
import glide.api.models.commands.bitmap.BitFieldOptions.Offset;
import glide.api.models.commands.bitmap.BitFieldOptions.OffsetMultiplier;
import glide.api.models.commands.bitmap.BitmapIndexType;
import glide.api.models.commands.bitmap.BitwiseOperation;
import java.util.concurrent.CompletableFuture;
Expand Down Expand Up @@ -237,4 +246,69 @@ CompletableFuture<Long> bitpos(
*/
CompletableFuture<Long> bitop(
BitwiseOperation bitwiseOperation, String destination, String[] keys);

/**
* Reads or modifies the array of bits representing the string that is held at <code>key</code>
* based on the specified <code>subCommands</code>.
*
* @see <a href="https://redis.io/commands/bitfield/">redis.io</a> for details.
* @param key The key of the string.
* @param subCommands The subCommands to be performed on the binary value of the string at <code>
* key</code>, which could be any of the following:
* <ul>
* <li>{@link BitFieldGet}.
* <li>{@link BitFieldSet}.
* <li>{@link BitFieldIncrby}.
* <li>{@link BitFieldOverflow}.
* </ul>
*
* @return An <code>array</code> of results from the executed subcommands.
* <ul>
* <li>{@link BitFieldGet} returns the value in {@link Offset} or {@link OffsetMultiplier}.
* <li>{@link BitFieldSet} returns the old value in {@link Offset} or {@link
* OffsetMultiplier}.
* <li>{@link BitFieldIncrby} returns the new value in {@link Offset} or {@link
* OffsetMultiplier}.
* <li>{@link BitFieldOverflow} determines the behaviour of <code>SET</code> and <code>
* INCRBY</code> when an overflow occurs. <code>OVERFLOW</code> does not return a value
* and does not contribute a value to the array response.
* </ul>
*
* @example
* <pre>{@code
* client.set("sampleKey", "A"); // "A" has binary value 01000001
* BitFieldSubCommands[] subcommands = new BitFieldSubCommands[] {
* new BitFieldSet(new UnsignedEncoding(2), new Offset(1), 3), // Sets the new binary value to 01100001
* new BitFieldGet(new UnsignedEncoding(2), new Offset(1)) // Gets value from 0(11)00001
* };
* Long[] payload = client.bitfield("sampleKey", subcommands).get();
* assertArrayEquals(payload, new Long[] {2L, 3L});
* }</pre>
*/
CompletableFuture<Long[]> bitfield(String key, BitFieldSubCommands[] subCommands);

/**
* Reads the array of bits representing the string that is held at <code>key</code> based on the
* specified <code>subCommands</code>.
*
* @since Redis 6.0 and above
* @see <a href="https://redis.io/docs/latest/commands/bitfield_ro/">redis.io</a> for details.
* @param key The key of the string.
* @param subCommands The <code>GET</code> subCommands to be performed.
* @return An array of results from the <code>GET</code> subcommands.
* @example
* <pre>{@code
* client.set("sampleKey", "A"); // "A" has binary value 01000001
* Long[] payload =
* client.
* bitfieldReadOnly(
* "sampleKey",
* new BitFieldReadOnlySubCommands[] {
* new BitFieldGet(new UnsignedEncoding(2), new Offset(1))
* })
* .get();
* assertArrayEquals(payload, new Long[] {2L}); // Value is from 0(10)00001
* }</pre>
*/
CompletableFuture<Long[]> bitfieldReadOnly(String key, BitFieldReadOnlySubCommands[] subCommands);
}
61 changes: 61 additions & 0 deletions java/client/src/main/java/glide/api/models/BaseTransaction.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import static glide.api.commands.SortedSetBaseCommands.WITH_SCORES_REDIS_API;
import static glide.api.commands.SortedSetBaseCommands.WITH_SCORE_REDIS_API;
import static glide.api.models.commands.RangeOptions.createZRangeArgs;
import static glide.api.models.commands.bitmap.BitFieldOptions.createBitFieldArgs;
import static glide.api.models.commands.function.FunctionLoadOptions.REPLACE;
import static glide.utils.ArrayTransformUtils.concatenateArrays;
import static glide.utils.ArrayTransformUtils.convertMapToKeyValueStringArray;
Expand All @@ -23,6 +24,8 @@
import static redis_request.RedisRequestOuterClass.RequestType.BZPopMax;
import static redis_request.RedisRequestOuterClass.RequestType.BZPopMin;
import static redis_request.RedisRequestOuterClass.RequestType.BitCount;
import static redis_request.RedisRequestOuterClass.RequestType.BitField;
import static redis_request.RedisRequestOuterClass.RequestType.BitFieldReadOnly;
import static redis_request.RedisRequestOuterClass.RequestType.BitOp;
import static redis_request.RedisRequestOuterClass.RequestType.BitPos;
import static redis_request.RedisRequestOuterClass.RequestType.ClientGetName;
Expand Down Expand Up @@ -185,6 +188,14 @@
import glide.api.models.commands.WeightAggregateOptions.KeysOrWeightedKeys;
import glide.api.models.commands.WeightAggregateOptions.WeightedKeys;
import glide.api.models.commands.ZAddOptions;
import glide.api.models.commands.bitmap.BitFieldOptions.BitFieldGet;
import glide.api.models.commands.bitmap.BitFieldOptions.BitFieldIncrby;
import glide.api.models.commands.bitmap.BitFieldOptions.BitFieldOverflow;
import glide.api.models.commands.bitmap.BitFieldOptions.BitFieldReadOnlySubCommands;
import glide.api.models.commands.bitmap.BitFieldOptions.BitFieldSet;
import glide.api.models.commands.bitmap.BitFieldOptions.BitFieldSubCommands;
import glide.api.models.commands.bitmap.BitFieldOptions.Offset;
import glide.api.models.commands.bitmap.BitFieldOptions.OffsetMultiplier;
import glide.api.models.commands.bitmap.BitmapIndexType;
import glide.api.models.commands.bitmap.BitwiseOperation;
import glide.api.models.commands.geospatial.GeoAddOptions;
Expand Down Expand Up @@ -3971,6 +3982,56 @@ public T srandmember(@NonNull String key, long count) {
return getThis();
}

/**
* Reads or modifies the array of bits representing the string that is held at <code>key</code>
* based on the specified <code>subCommands</code>.
*
* @see <a href="https://redis.io/commands/bitfield/">redis.io</a> for details.
* @param key The key of the string.
* @param subCommands The subCommands to be performed on the binary value of the string at <code>
* key</code>, which could be any of the following:
* <ul>
* <li>{@link BitFieldGet}.
* <li>{@link BitFieldSet}.
* <li>{@link BitFieldIncrby}.
* <li>{@link BitFieldOverflow}.
* </ul>
*
* @return Command Response - An <code>array</code> of results from the executed subcommands.
* <ul>
* <li>{@link BitFieldGet} returns the value in {@link Offset} or {@link OffsetMultiplier}.
* <li>{@link BitFieldSet} returns the old value in {@link Offset} or {@link
* OffsetMultiplier}.
* <li>{@link BitFieldIncrby} returns the new value in {@link Offset} or {@link
* OffsetMultiplier}.
* <li>{@link BitFieldOverflow} determines the behaviour of <code>SET</code> and <code>
* INCRBY</code> when an overflow occurs. <code>OVERFLOW</code> does not return a value
* and does not contribute a value to the array response.
* </ul>
*/
public T bitfield(@NonNull String key, @NonNull BitFieldSubCommands[] subCommands) {
ArgsArray commandArgs = buildArgs(ArrayUtils.addFirst(createBitFieldArgs(subCommands), key));
protobufTransaction.addCommands(buildCommand(BitField, commandArgs));
return getThis();
}

/**
* Reads the array of bits representing the string that is held at <code>key</code> based on the
* specified <code>subCommands</code>.
*
* @since Redis 6.0 and above
* @see <a href="https://redis.io/docs/latest/commands/bitfield_ro/">redis.io</a> for details.
* @param key The key of the string.
* @param subCommands The <code>GET</code> subCommands to be performed.
* @return Command Response - An array of results from the <code>GET</code> subcommands.
*/
public T bitfieldReadOnly(
@NonNull String key, @NonNull BitFieldReadOnlySubCommands[] subCommands) {
ArgsArray commandArgs = buildArgs(ArrayUtils.addFirst(createBitFieldArgs(subCommands), key));
protobufTransaction.addCommands(buildCommand(BitFieldReadOnly, commandArgs));
return getThis();
}

/** Build protobuf {@link Command} object for given command and arguments. */
protected Command buildCommand(RequestType requestType) {
return buildCommand(requestType, buildArgs());
Expand Down
Loading
Loading