Skip to content

Commit

Permalink
Support integer width multiplied offsets in BITFIELD #379
Browse files Browse the repository at this point in the history
BitFieldArgs exposes now BitFieldArgs.offset and BitFieldArgs.typeWidthBasedOffset factory methods to create Offset instances that can be used together with BITFIELD subcommands.
  • Loading branch information
mp911de committed Oct 24, 2016
1 parent b8eacfd commit 0a0d23c
Show file tree
Hide file tree
Showing 2 changed files with 254 additions and 25 deletions.
233 changes: 209 additions & 24 deletions src/main/java/com/lambdaworks/redis/BitFieldArgs.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ private Builder() {
}

/**
* Adds a new {@link Get} subcommand.
* Create a new {@link Get} subcommand.
*
* @param bitFieldType the bit field type, must not be {@literal null}.
* @param offset bitfield offset
Expand All @@ -53,7 +53,19 @@ public static BitFieldArgs get(BitFieldType bitFieldType, int offset) {
}

/**
* Adds a new {@link Set} subcommand.
* Create a new {@link Get} subcommand.
*
* @param bitFieldType the bit field type, must not be {@literal null}.
* @param offset bitfield offset, must not be {@literal null}.
* @return a new {@link Get} subcommand for the given {@code bitFieldType} and {@code offset}.
* @since 4.3
*/
public static BitFieldArgs get(BitFieldType bitFieldType, Offset offset) {
return new BitFieldArgs().get(bitFieldType, offset);
}

/**
* Create a new {@link Set} subcommand.
*
* @param bitFieldType the bit field type, must not be {@literal null}.
* @param offset bitfield offset
Expand All @@ -65,7 +77,20 @@ public static BitFieldArgs set(BitFieldType bitFieldType, int offset, long value
}

/**
* Adds a new {@link IncrBy} subcommand.
* Create a new {@link Set} subcommand.
*
* @param bitFieldType the bit field type, must not be {@literal null}.
* @param offset bitfield offset, must not be {@literal null}.
* @param value the value
* @return a new {@link Set} subcommand for the given {@code bitFieldType}, {@code offset} and {@code value}.
* @since 4.3
*/
public static BitFieldArgs set(BitFieldType bitFieldType, Offset offset, long value) {
return new BitFieldArgs().set(bitFieldType, offset, value);
}

/**
* Create a new {@link IncrBy} subcommand.
*
* @param bitFieldType the bit field type, must not be {@literal null}.
* @param offset bitfield offset
Expand All @@ -76,6 +101,19 @@ public static BitFieldArgs incrBy(BitFieldType bitFieldType, int offset, long va
return new BitFieldArgs().incrBy(bitFieldType, offset, value);
}

/**
* Create a new {@link IncrBy} subcommand.
*
* @param bitFieldType the bit field type, must not be {@literal null}.
* @param offset bitfield offset, must not be {@literal null}.
* @param value the value
* @return a new {@link IncrBy} subcommand for the given {@code bitFieldType}, {@code offset} and {@code value}.
* @since 4.3
*/
public static BitFieldArgs incrBy(BitFieldType bitFieldType, Offset offset, long value) {
return new BitFieldArgs().incrBy(bitFieldType, offset, value);
}

/**
* Adds a new {@link Overflow} subcommand.
*
Expand All @@ -92,8 +130,8 @@ public static BitFieldArgs overflow(OverflowType overflowType) {
*
* Redis allows up to {@code 64} bits for unsigned integers.
*
* @param bits
* @return
* @param bits number of bits to define the integer type width.
* @return the {@link BitFieldType}.
*/
public static BitFieldType signed(int bits) {
return new BitFieldType(true, bits);
Expand All @@ -103,19 +141,43 @@ public static BitFieldType signed(int bits) {
* Creates a new unsigned {@link BitFieldType} for the given number of {@code bits}. Redis allows up to {@code 63} bits for
* unsigned integers.
*
* @param bits
* @return
* @param bits number of bits to define the integer type width.
* @return the {@link BitFieldType}.
*/
public static BitFieldType unsigned(int bits) {
return new BitFieldType(false, bits);
}

/**
* Creates a new {@link Offset} for the given {@code offset}.
*
* @param offset zero-based offset.
* @return the {@link Offset}.
* @since 4.3
*/
public static Offset offset(int offset) {
return new Offset(false, offset);
}

/**
* Creates a new {@link Offset} for the given {@code offset} that is multiplied by the integer type width used in the sub
* command.
*
* @param offset offset to be multiplied by the integer type width.
* @return the {@link Offset}.
* @since 4.3
*/
public static Offset typeWidthBasedOffset(int offset) {
return new Offset(true, offset);
}

/**
* Adds a new {@link SubCommand} to the {@code BITFIELD} execution.
*
* @param subCommand
* @param subCommand must not be {@literal null}.
*/
private BitFieldArgs addSubCommand(SubCommand subCommand) {

LettuceAssert.notNull(subCommand, "SubCommand must not be null");
commands.add(subCommand);
return this;
Expand Down Expand Up @@ -149,7 +211,22 @@ public BitFieldArgs get(BitFieldType bitFieldType) {
* @return a new {@link Get} subcommand for the given {@code bitFieldType} and {@code offset}.
*/
public BitFieldArgs get(BitFieldType bitFieldType, int offset) {
return addSubCommand(new Get(bitFieldType, offset));
return addSubCommand(new Get(bitFieldType, false, offset));
}

/**
* Adds a new {@link Get} subcommand.
*
* @param bitFieldType the bit field type, must not be {@literal null}.
* @param offset bitfield offset
* @return a new {@link Get} subcommand for the given {@code bitFieldType} and {@code offset}.
* @since 4.3
*/
public BitFieldArgs get(BitFieldType bitFieldType, Offset offset) {

LettuceAssert.notNull(offset, "BitFieldOffset must not be null");

return addSubCommand(new Get(bitFieldType, offset.isMultiplyByTypeWidth(), offset.getOffset()));
}

/**
Expand Down Expand Up @@ -206,7 +283,23 @@ public BitFieldArgs set(int offset, long value) {
* @return a new {@link Set} subcommand for the given {@code bitFieldType}, {@code offset} and {@code value}.
*/
public BitFieldArgs set(BitFieldType bitFieldType, int offset, long value) {
return addSubCommand(new Set(bitFieldType, offset, value));
return addSubCommand(new Set(bitFieldType, false, offset, value));
}

/**
* Adds a new {@link Set} subcommand.
*
* @param bitFieldType the bit field type, must not be {@literal null}.
* @param offset bitfield offset, must not be {@literal null}.
* @param value the value
* @return a new {@link Set} subcommand for the given {@code bitFieldType}, {@code offset} and {@code value}.
* @since 4.3
*/
public BitFieldArgs set(BitFieldType bitFieldType, Offset offset, long value) {

LettuceAssert.notNull(offset, "BitFieldOffset must not be null");

return addSubCommand(new Set(bitFieldType, offset.isMultiplyByTypeWidth(), offset.getOffset(), value));
}

/**
Expand Down Expand Up @@ -252,7 +345,23 @@ public BitFieldArgs incrBy(int offset, long value) {
* @return a new {@link IncrBy} subcommand for the given {@code bitFieldType}, {@code offset} and {@code value}.
*/
public BitFieldArgs incrBy(BitFieldType bitFieldType, int offset, long value) {
return addSubCommand(new IncrBy(bitFieldType, offset, value));
return addSubCommand(new IncrBy(bitFieldType, false, offset, value));
}

/**
* Adds a new {@link IncrBy} subcommand.
*
* @param bitFieldType the bit field type, must not be {@literal null}.
* @param offset bitfield offset, must not be {@literal null}.
* @param value the value
* @return a new {@link IncrBy} subcommand for the given {@code bitFieldType}, {@code offset} and {@code value}.
* @since 4.3
*/
public BitFieldArgs incrBy(BitFieldType bitFieldType, Offset offset, long value) {

LettuceAssert.notNull(offset, "BitFieldOffset must not be null");

return addSubCommand(new IncrBy(bitFieldType, offset.isMultiplyByTypeWidth(), offset.getOffset(), value));
}

/**
Expand Down Expand Up @@ -294,22 +403,33 @@ private BitFieldType previousFieldType() {
private static class Set extends SubCommand {

private final BitFieldType bitFieldType;
private final boolean bitOffset;
private final long offset;
private final long value;

private Set(BitFieldType bitFieldType, int offset, long value) {
private Set(BitFieldType bitFieldType, boolean bitOffset, int offset, long value) {

LettuceAssert.notNull(bitFieldType, "BitFieldType must not be null");
LettuceAssert.isTrue(offset > -1, "Offset must be greater or equal to 0");

this.offset = offset;
this.bitFieldType = bitFieldType;
this.bitOffset = bitOffset;
this.offset = offset;
this.value = value;
}

@Override
<K, V> void build(CommandArgs<K, V> args) {
args.add(CommandType.SET).add(bitFieldType.asString()).add(offset).add(value);

args.add(CommandType.SET).add(bitFieldType.asString());

if (bitOffset) {
args.add(String.format("#%d", offset));
} else {
args.add(offset);
}

args.add(value);
}
}

Expand All @@ -319,20 +439,29 @@ <K, V> void build(CommandArgs<K, V> args) {
private static class Get extends SubCommand {

private final BitFieldType bitFieldType;
private final long offset;
private final boolean bitOffset;
private final int offset;

private Get(BitFieldType bitFieldType, int offset) {
private Get(BitFieldType bitFieldType, boolean bitOffset, int offset) {

LettuceAssert.notNull(bitFieldType, "BitFieldType must not be null");
LettuceAssert.isTrue(offset > -1, "Offset must be greater or equal to 0");

this.offset = offset;
this.bitFieldType = bitFieldType;
this.bitOffset = bitOffset;
this.offset = offset;
}

@Override
<K, V> void build(CommandArgs<K, V> args) {
args.add(CommandType.GET).add(bitFieldType.asString()).add(offset);

args.add(CommandType.GET).add(bitFieldType.asString());

if (bitOffset) {
args.add(String.format("#%d", offset));
} else {
args.add(offset);
}
}
}

Expand All @@ -342,22 +471,34 @@ <K, V> void build(CommandArgs<K, V> args) {
private static class IncrBy extends SubCommand {

private final BitFieldType bitFieldType;
private final boolean bitOffset;
private final long offset;
private final long value;

private IncrBy(BitFieldType bitFieldType, int offset, long value) {
private IncrBy(BitFieldType bitFieldType, boolean offsetWidthMultiplier, int offset, long value) {

LettuceAssert.notNull(bitFieldType, "BitFieldType must not be null");
LettuceAssert.isTrue(offset > -1, "Offset must be greater or equal to 0");

this.offset = offset;
this.bitFieldType = bitFieldType;
this.bitOffset = offsetWidthMultiplier;
this.offset = offset;
this.value = value;
}

@Override
<K, V> void build(CommandArgs<K, V> args) {
args.add(CommandType.INCRBY).add(bitFieldType.asString()).add(offset).add(value);

args.add(CommandType.INCRBY).add(bitFieldType.asString());

if (bitOffset) {
args.add(String.format("#%d", offset));
} else {
args.add(offset);
}

args.add(value);

}
}

Expand Down Expand Up @@ -403,7 +544,7 @@ public enum OverflowType implements ProtocolKeyword {

public final byte[] bytes;

private OverflowType() {
OverflowType() {
bytes = name().getBytes(LettuceCharsets.ASCII);
}

Expand Down Expand Up @@ -451,8 +592,52 @@ public int getBits() {
return bits;
}

private String asString() {
return (signed ? "i" : "u") + bits;
private String asString() {
return String.format("%s%d", (signed ? "i" : "u"), bits);
}

@Override
public String toString() {
return asString();
}
}

/**
* Represents a bit field offset. See also <a href="http://redis.io/commands/bitfield#bits-and-positional-offsets">Bits and
* positional offsets</a>
*
* @since 4.3
*/
public static class Offset {

private final boolean multiplyByTypeWidth;
private final int offset;

private Offset(boolean multiplyByTypeWidth, int offset) {

this.multiplyByTypeWidth = multiplyByTypeWidth;
this.offset = offset;
}

/**
* @return {@literal true} if the offset should be multiplied by integer width that is represented with a leading hash
* ({@code #}) when constructing the command
*/
public boolean isMultiplyByTypeWidth() {
return multiplyByTypeWidth;
}

/**
*
* @return the offset.
*/
public int getOffset() {
return offset;
}

@Override
public String toString() {
return String.format("%s%d", (multiplyByTypeWidth ? "#" : ""), offset);
}
}
}

0 comments on commit 0a0d23c

Please sign in to comment.