-
Notifications
You must be signed in to change notification settings - Fork 2
Bitmap command support #129
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
Merged
+1,267
−8
Merged
Changes from all commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
b9f3999
Add bitadd
alexr-bq 9b153f1
Add setbit
alexr-bq 1eb3450
bitcount
alexr-bq 41354dc
bitop
alexr-bq 7d791df
Implement bitfield
alexr-bq 1caa4b4
resolve merge conflict
alexr-bq be58852
Batch and unit tests
alexr-bq 872b1d8
Update version in readme
alexr-bq a86f508
Merge branch 'main' into alexr/bitmap
alexr-bq 8cb17a1
Format
alexr-bq 56f47c0
Attempt to set higher timeout for tests
alexr-bq 532f007
Merge branch 'main' of github.com:valkey-io/valkey-glide-csharp into …
alexr-bq 6b0cb34
Add skip for tests of functionality only supported in server versions…
alexr-bq 560a37e
Update sources/Valkey.Glide/Commands/IBitmapCommands.cs
alexr-bq 0b66516
Update tests/Valkey.Glide.IntegrationTests/BitmapCommandTests.cs
alexr-bq ab09d51
Resolve PR feedback
alexr-bq File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,77 @@ | ||
| // Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0 | ||
|
|
||
| using Valkey.Glide.Commands; | ||
| using Valkey.Glide.Commands.Options; | ||
| using Valkey.Glide.Internals; | ||
|
|
||
| namespace Valkey.Glide; | ||
|
|
||
| public abstract partial class BaseClient : IBitmapCommands | ||
| { | ||
| /// <inheritdoc/> | ||
| public async Task<bool> StringGetBitAsync(ValkeyKey key, long offset, CommandFlags flags = CommandFlags.None) | ||
| { | ||
| Utils.Requires<NotImplementedException>(flags == CommandFlags.None, "Command flags are not supported by GLIDE"); | ||
currantw marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| return await Command(Request.GetBitAsync(key, offset)); | ||
| } | ||
|
|
||
| /// <inheritdoc/> | ||
| public async Task<bool> StringSetBitAsync(ValkeyKey key, long offset, bool value, CommandFlags flags = CommandFlags.None) | ||
| { | ||
| Utils.Requires<NotImplementedException>(flags == CommandFlags.None, "Command flags are not supported by GLIDE"); | ||
| return await Command(Request.SetBitAsync(key, offset, value)); | ||
| } | ||
|
|
||
| /// <inheritdoc/> | ||
| public async Task<long> StringBitCountAsync(ValkeyKey key, long start = 0, long end = -1, StringIndexType indexType = StringIndexType.Byte, CommandFlags flags = CommandFlags.None) | ||
| { | ||
| Utils.Requires<NotImplementedException>(flags == CommandFlags.None, "Command flags are not supported by GLIDE"); | ||
| return await Command(Request.BitCountAsync(key, start, end, indexType)); | ||
| } | ||
|
|
||
| /// <inheritdoc/> | ||
| public async Task<long> StringBitPositionAsync(ValkeyKey key, bool bit, long start = 0, long end = -1, StringIndexType indexType = StringIndexType.Byte, CommandFlags flags = CommandFlags.None) | ||
| { | ||
| Utils.Requires<NotImplementedException>(flags == CommandFlags.None, "Command flags are not supported by GLIDE"); | ||
| return await Command(Request.BitPositionAsync(key, bit, start, end, indexType)); | ||
| } | ||
|
|
||
| /// <inheritdoc/> | ||
| public async Task<long> StringBitOperationAsync(Bitwise operation, ValkeyKey destination, ValkeyKey first, ValkeyKey second, CommandFlags flags = CommandFlags.None) | ||
| { | ||
| Utils.Requires<NotImplementedException>(flags == CommandFlags.None, "Command flags are not supported by GLIDE"); | ||
| return await Command(Request.BitOperationAsync(operation, destination, first, second)); | ||
| } | ||
|
|
||
| /// <inheritdoc/> | ||
| public async Task<long> StringBitOperationAsync(Bitwise operation, ValkeyKey destination, ValkeyKey[] keys, CommandFlags flags = CommandFlags.None) | ||
| { | ||
| Utils.Requires<NotImplementedException>(flags == CommandFlags.None, "Command flags are not supported by GLIDE"); | ||
| return await Command(Request.BitOperationAsync(operation, destination, keys)); | ||
| } | ||
|
|
||
| /// <inheritdoc/> | ||
| public async Task<long[]> StringBitFieldAsync(ValkeyKey key, BitFieldOptions.IBitFieldSubCommand[] subCommands, CommandFlags flags = CommandFlags.None) | ||
| { | ||
| Utils.Requires<NotImplementedException>(flags == CommandFlags.None, "Command flags are not supported by GLIDE"); | ||
|
|
||
| // Check if all subcommands are read-only (GET operations) | ||
| bool allReadOnly = subCommands.All(cmd => cmd is BitFieldOptions.IBitFieldReadOnlySubCommand); | ||
|
|
||
| if (allReadOnly) | ||
| { | ||
| // Convert to read-only subcommands and use BITFIELD_RO | ||
| var readOnlyCommands = subCommands.Cast<BitFieldOptions.IBitFieldReadOnlySubCommand>().ToArray(); | ||
| return await Command(Request.BitFieldReadOnlyAsync(key, readOnlyCommands)); | ||
| } | ||
|
|
||
| return await Command(Request.BitFieldAsync(key, subCommands)); | ||
| } | ||
|
|
||
| /// <inheritdoc/> | ||
| public async Task<long[]> StringBitFieldReadOnlyAsync(ValkeyKey key, BitFieldOptions.IBitFieldReadOnlySubCommand[] subCommands, CommandFlags flags = CommandFlags.None) | ||
| { | ||
| Utils.Requires<NotImplementedException>(flags == CommandFlags.None, "Command flags are not supported by GLIDE"); | ||
| return await Command(Request.BitFieldReadOnlyAsync(key, subCommands)); | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,183 @@ | ||
| // Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0 | ||
|
|
||
| namespace Valkey.Glide.Commands; | ||
|
|
||
| /// <summary> | ||
| /// Supports bitmap commands for standalone and cluster clients. | ||
| /// <br/> | ||
| /// See more on <see href="https://valkey.io/commands#bitmap">valkey.io</see>. | ||
| /// </summary> | ||
| public interface IBitmapCommands | ||
| { | ||
| /// <summary> | ||
| /// Returns the bit value at offset in the string value stored at key. | ||
| /// </summary> | ||
| /// <seealso href="https://valkey.io/commands/getbit"/> | ||
| /// <param name="key">The key of the string.</param> | ||
| /// <param name="offset">The offset in the string to get the bit at.</param> | ||
| /// <param name="flags">The flags to use for this operation. Currently flags are ignored.</param> | ||
| /// <returns>The bit value stored at offset. Returns 0 if the key does not exist or if the offset is beyond the string length.</returns> | ||
| /// <remarks> | ||
| /// <example> | ||
| /// <code> | ||
| /// await client.StringSetAsync("mykey", "A"); // ASCII 'A' is 01000001 | ||
| /// bool bit = await client.StringGetBitAsync("mykey", 1); | ||
| /// Console.WriteLine(bit); // Output: true (bit 1 is set) | ||
| /// </code> | ||
| /// </example> | ||
| /// </remarks> | ||
| Task<bool> StringGetBitAsync(ValkeyKey key, long offset, CommandFlags flags = CommandFlags.None); | ||
|
|
||
| /// <summary> | ||
| /// Sets or clears the bit at offset in the string value stored at key. | ||
| /// </summary> | ||
| /// <seealso href="https://valkey.io/commands/setbit"/> | ||
| /// <param name="key">The key of the string.</param> | ||
| /// <param name="offset">The offset in the string to set the bit at.</param> | ||
| /// <param name="value">The bit value to set (true for 1, false for 0).</param> | ||
| /// <param name="flags">The flags to use for this operation. Currently flags are ignored.</param> | ||
| /// <returns>The original bit value stored at offset. Returns false if the key does not exist or if the offset is beyond the string length.</returns> | ||
| /// <remarks> | ||
| /// <example> | ||
| /// <code> | ||
| /// bool oldBit = await client.StringSetBitAsync("mykey", 1, true); | ||
| /// Console.WriteLine(oldBit); // Output: false (original bit value) | ||
| /// </code> | ||
| /// </example> | ||
| /// </remarks> | ||
| Task<bool> StringSetBitAsync(ValkeyKey key, long offset, bool value, CommandFlags flags = CommandFlags.None); | ||
|
|
||
| /// <summary> | ||
| /// Count the number of set bits in a string. | ||
| /// </summary> | ||
| /// <seealso href="https://valkey.io/commands/bitcount"/> | ||
| /// <param name="key">The key of the string.</param> | ||
| /// <param name="start">The start offset.</param> | ||
| /// <param name="end">The end offset.</param> | ||
| /// <param name="indexType">The index type (bit or byte).</param> | ||
| /// <param name="flags">The flags to use for this operation. Currently flags are ignored.</param> | ||
| /// <returns>The number of bits set to 1.</returns> | ||
| /// <remarks> | ||
| /// <example> | ||
| /// <code> | ||
| /// await client.StringSetAsync("mykey", "A"); // ASCII 'A' is 01000001 | ||
| /// long count = await client.StringBitCountAsync("mykey"); | ||
| /// Console.WriteLine(count); // Output: 2 (two bits set) | ||
| /// </code> | ||
| /// </example> | ||
| /// </remarks> | ||
| Task<long> StringBitCountAsync(ValkeyKey key, long start = 0, long end = -1, StringIndexType indexType = StringIndexType.Byte, CommandFlags flags = CommandFlags.None); | ||
|
|
||
| /// <summary> | ||
| /// Return the position of the first bit set to 1 or 0 in a string. | ||
| /// </summary> | ||
| /// <seealso href="https://valkey.io/commands/bitpos"/> | ||
| /// <param name="key">The key of the string.</param> | ||
| /// <param name="bit">The bit value to search for (true for 1, false for 0).</param> | ||
| /// <param name="start">The start offset.</param> | ||
| /// <param name="end">The end offset.</param> | ||
| /// <param name="indexType">The index type (bit or byte).</param> | ||
| /// <param name="flags">The flags to use for this operation. Currently flags are ignored.</param> | ||
| /// <returns>The position of the first bit with the specified value, or -1 if not found.</returns> | ||
| /// <remarks> | ||
| /// <example> | ||
| /// <code> | ||
| /// await client.StringSetAsync("mykey", "A"); // ASCII 'A' is 01000001 | ||
| /// long pos = await client.StringBitPositionAsync("mykey", true); | ||
| /// Console.WriteLine(pos); // Output: 1 (first set bit at position 1) | ||
| /// </code> | ||
| /// </example> | ||
| /// </remarks> | ||
| Task<long> StringBitPositionAsync(ValkeyKey key, bool bit, long start = 0, long end = -1, StringIndexType indexType = StringIndexType.Byte, CommandFlags flags = CommandFlags.None); | ||
|
|
||
| /// <summary> | ||
| /// Perform a bitwise operation between multiple keys and store the result in the destination key. | ||
| /// </summary> | ||
| /// <seealso href="https://valkey.io/commands/bitop"/> | ||
| /// <param name="operation">The bitwise operation to perform.</param> | ||
| /// <param name="destination">The key to store the result.</param> | ||
| /// <param name="first">The first source key.</param> | ||
| /// <param name="second">The second source key.</param> | ||
| /// <param name="flags">The flags to use for this operation. Currently flags are ignored.</param> | ||
| /// <returns>The size of the string stored in the destination key.</returns> | ||
| /// <remarks> | ||
| /// <example> | ||
| /// <code> | ||
| /// await client.StringSetAsync("key1", "A"); | ||
| /// await client.StringSetAsync("key2", "B"); | ||
| /// long size = await client.StringBitOperationAsync(Bitwise.And, "result", "key1", "key2"); | ||
| /// Console.WriteLine(size); // Output: 1 (size of result) | ||
| /// </code> | ||
| /// </example> | ||
| /// </remarks> | ||
| Task<long> StringBitOperationAsync(Bitwise operation, ValkeyKey destination, ValkeyKey first, ValkeyKey second, CommandFlags flags = CommandFlags.None); | ||
|
|
||
| /// <summary> | ||
| /// Perform a bitwise operation between multiple keys and store the result in the destination key. | ||
| /// </summary> | ||
| /// <seealso href="https://valkey.io/commands/bitop"/> | ||
| /// <param name="operation">The bitwise operation to perform.</param> | ||
| /// <param name="destination">The key to store the result.</param> | ||
| /// <param name="keys">The source keys.</param> | ||
| /// <param name="flags">The flags to use for this operation. Currently flags are ignored.</param> | ||
| /// <returns>The size of the string stored in the destination key.</returns> | ||
| /// <remarks> | ||
| /// <example> | ||
| /// <code> | ||
| /// await client.StringSetAsync("key1", "A"); | ||
| /// await client.StringSetAsync("key2", "B"); | ||
| /// await client.StringSetAsync("key3", "C"); | ||
| /// long size = await client.StringBitOperationAsync(Bitwise.Or, "result", new ValkeyKey[] { "key1", "key2", "key3" }); | ||
| /// Console.WriteLine(size); // Output: 1 (size of result) | ||
| /// </code> | ||
| /// </example> | ||
| /// </remarks> | ||
| Task<long> StringBitOperationAsync(Bitwise operation, ValkeyKey destination, ValkeyKey[] keys, CommandFlags flags = CommandFlags.None); | ||
|
|
||
| /// <summary> | ||
| /// Reads or modifies the array of bits representing the string stored at key based on the specified subcommands. | ||
| /// </summary> | ||
| /// <seealso href="https://valkey.io/commands/bitfield"/> | ||
| /// <param name="key">The key of the string.</param> | ||
| /// <param name="subCommands">The subcommands to execute (GET, SET, INCRBY).</param> | ||
| /// <param name="flags">The flags to use for this operation. Currently flags are ignored.</param> | ||
| /// <returns>An array of results from the executed subcommands. Null responses from the server are converted to 0.</returns> | ||
| /// <remarks> | ||
| /// <example> | ||
| /// <code> | ||
| /// await client.StringSetAsync("mykey", "A"); // ASCII 'A' is 01000001 | ||
| /// var subCommands = new IBitFieldSubCommand[] { | ||
| /// new BitFieldOptions.BitFieldGet(BitFieldOptions.Encoding.Unsigned(8), 0), | ||
| /// new BitFieldOptions.BitFieldSet(BitFieldOptions.Encoding.Unsigned(8), 0, 66) // ASCII 'B' | ||
| /// }; | ||
| /// long[] results = await client.StringBitFieldAsync("mykey", subCommands); | ||
| /// Console.WriteLine(results[0]); // Output: 65 (ASCII 'A') | ||
| /// Console.WriteLine(results[1]); // Output: 65 (old value) | ||
| /// </code> | ||
| /// </example> | ||
| /// </remarks> | ||
| Task<long[]> StringBitFieldAsync(ValkeyKey key, Commands.Options.BitFieldOptions.IBitFieldSubCommand[] subCommands, CommandFlags flags = CommandFlags.None); | ||
|
|
||
| /// <summary> | ||
| /// Reads the array of bits representing the string stored at key based on the specified GET subcommands. | ||
| /// This is a read-only variant of BITFIELD. | ||
| /// </summary> | ||
| /// <seealso href="https://valkey.io/commands/bitfield_ro"/> | ||
| /// <param name="key">The key of the string.</param> | ||
| /// <param name="subCommands">The GET subcommands to execute.</param> | ||
| /// <param name="flags">The flags to use for this operation. Currently flags are ignored.</param> | ||
| /// <returns>An array of results from the executed GET subcommands. Null responses from the server are converted to 0.</returns> | ||
| /// <remarks> | ||
| /// <example> | ||
| /// <code> | ||
| /// await client.StringSetAsync("mykey", "A"); // ASCII 'A' is 01000001 | ||
| /// var subCommands = new IBitFieldReadOnlySubCommand[] { | ||
| /// new BitFieldOptions.BitFieldGet(BitFieldOptions.Encoding.Unsigned(8), 0) | ||
| /// }; | ||
| /// long[] results = await client.StringBitFieldReadOnlyAsync("mykey", subCommands); | ||
| /// Console.WriteLine(results[0]); // Output: 65 (ASCII 'A') | ||
| /// </code> | ||
| /// </example> | ||
| /// </remarks> | ||
| Task<long[]> StringBitFieldReadOnlyAsync(ValkeyKey key, Commands.Options.BitFieldOptions.IBitFieldReadOnlySubCommand[] subCommands, CommandFlags flags = CommandFlags.None); | ||
| } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.