From 7e1120db7cae72b07d78fb677bb700cddac56c87 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Mon, 9 Oct 2017 22:57:56 +0200 Subject: [PATCH] Introduce BITPOS override to accept start without end position #623 --- pom.xml | 2 +- .../core/AbstractRedisAsyncCommands.java | 5 +++ .../core/AbstractRedisReactiveCommands.java | 5 +++ .../io/lettuce/core/RedisCommandBuilder.java | 8 +++++ .../api/async/RedisStringAsyncCommands.java | 35 ++++++++++++++----- .../reactive/RedisStringReactiveCommands.java | 31 +++++++++++----- .../core/api/sync/RedisStringCommands.java | 33 +++++++++++++---- .../NodeSelectionStringAsyncCommands.java | 34 ++++++++++++++---- .../api/sync/NodeSelectionStringCommands.java | 33 +++++++++++++---- .../lettuce/core/api/RedisStringCommands.java | 25 ++++++++++--- .../lettuce/apigenerator/CreateAsyncApi.java | 2 +- .../CreateAsyncNodeSelectionClusterApi.java | 2 +- .../apigenerator/CreateReactiveApi.java | 2 +- .../lettuce/apigenerator/CreateSyncApi.java | 2 +- .../CreateSyncNodeSelectionClusterApi.java | 2 +- .../lettuce/core/commands/BitCommandTest.java | 6 ++-- 16 files changed, 178 insertions(+), 49 deletions(-) diff --git a/pom.xml b/pom.xml index 63de5c2012..9b07e22a2c 100644 --- a/pom.xml +++ b/pom.xml @@ -353,7 +353,7 @@ com.github.javaparser javaparser-core - 2.5.1 + 2.3.0 test diff --git a/src/main/java/io/lettuce/core/AbstractRedisAsyncCommands.java b/src/main/java/io/lettuce/core/AbstractRedisAsyncCommands.java index 459cf5ee73..8dd3aa3b2d 100644 --- a/src/main/java/io/lettuce/core/AbstractRedisAsyncCommands.java +++ b/src/main/java/io/lettuce/core/AbstractRedisAsyncCommands.java @@ -135,6 +135,11 @@ public RedisFuture bitpos(K key, boolean state) { return dispatch(commandBuilder.bitpos(key, state)); } + @Override + public RedisFuture bitpos(K key, boolean state, long start) { + return dispatch(commandBuilder.bitpos(key, state, start)); + } + @Override public RedisFuture bitpos(K key, boolean state, long start, long end) { return dispatch(commandBuilder.bitpos(key, state, start, end)); diff --git a/src/main/java/io/lettuce/core/AbstractRedisReactiveCommands.java b/src/main/java/io/lettuce/core/AbstractRedisReactiveCommands.java index d4f6343983..6937754974 100644 --- a/src/main/java/io/lettuce/core/AbstractRedisReactiveCommands.java +++ b/src/main/java/io/lettuce/core/AbstractRedisReactiveCommands.java @@ -129,6 +129,11 @@ public Mono bitpos(K key, boolean state) { return createMono(() -> commandBuilder.bitpos(key, state)); } + @Override + public Mono bitpos(K key, boolean state, long start) { + return createMono(() -> commandBuilder.bitpos(key, state, start)); + } + @Override public Mono bitpos(K key, boolean state, long start, long end) { return createMono(() -> commandBuilder.bitpos(key, state, start, end)); diff --git a/src/main/java/io/lettuce/core/RedisCommandBuilder.java b/src/main/java/io/lettuce/core/RedisCommandBuilder.java index 911f3a7892..5f1aded5d2 100644 --- a/src/main/java/io/lettuce/core/RedisCommandBuilder.java +++ b/src/main/java/io/lettuce/core/RedisCommandBuilder.java @@ -167,6 +167,14 @@ Command bitpos(K key, boolean state) { return createCommand(BITPOS, new IntegerOutput<>(codec), args); } + Command bitpos(K key, boolean state, long start) { + notNullKey(key); + + CommandArgs args = new CommandArgs<>(codec); + args.addKey(key).add(state ? 1 : 0).add(start); + return createCommand(BITPOS, new IntegerOutput<>(codec), args); + } + Command bitpos(K key, boolean state, long start, long end) { notNullKey(key); diff --git a/src/main/java/io/lettuce/core/api/async/RedisStringAsyncCommands.java b/src/main/java/io/lettuce/core/api/async/RedisStringAsyncCommands.java index 31369b450e..98c2cf7c5b 100644 --- a/src/main/java/io/lettuce/core/api/async/RedisStringAsyncCommands.java +++ b/src/main/java/io/lettuce/core/api/async/RedisStringAsyncCommands.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2016 the original author or authors. + * Copyright 2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,12 +17,14 @@ import java.util.List; import java.util.Map; - +import io.lettuce.core.output.KeyValueStreamingChannel; +import io.lettuce.core.output.ValueStreamingChannel; import io.lettuce.core.BitFieldArgs; import io.lettuce.core.KeyValue; -import io.lettuce.core.RedisFuture; import io.lettuce.core.SetArgs; -import io.lettuce.core.output.KeyValueStreamingChannel; +import io.lettuce.core.Value; +import io.lettuce.core.RedisFuture; +import reactor.core.publisher.Mono; /** * Asynchronous executed commands for Strings. @@ -91,13 +93,30 @@ public interface RedisStringAsyncCommands { * * Basically the function consider the right of the string as padded with zeros if you look for clear bits and * specify no range or the start argument only. - * - * However this behavior changes if you are looking for clear bits and specify a range with both - * start and end. If no clear bit is found in the specified range, the function - * returns -1 as the user specified a clear range and there are no 0 bits in that range. */ RedisFuture bitpos(K key, boolean state); + /** + * Find first bit set or clear in a string. + * + * @param key the key + * @param state the bit type: long + * @param start the start type: long + * @return Long integer-reply The command returns the position of the first bit set to 1 or 0 according to the request. + * + * If we look for set bits (the bit argument is 1) and the string is empty or composed of just zero bytes, -1 is + * returned. + * + * If we look for clear bits (the bit argument is 0) and the string only contains bit set to 1, the function returns + * the first bit not part of the string on the right. So if the string is tree bytes set to the value 0xff the + * command {@code BITPOS key 0} will return 24, since up to bit 23 all the bits are 1. + * + * Basically the function consider the right of the string as padded with zeros if you look for clear bits and + * specify no range or the start argument only. + * @since 5.0.1 + */ + RedisFuture bitpos(K key, boolean state, long start); + /** * Find first bit set or clear in a string. * diff --git a/src/main/java/io/lettuce/core/api/reactive/RedisStringReactiveCommands.java b/src/main/java/io/lettuce/core/api/reactive/RedisStringReactiveCommands.java index b5c72ffcb6..584a657f36 100644 --- a/src/main/java/io/lettuce/core/api/reactive/RedisStringReactiveCommands.java +++ b/src/main/java/io/lettuce/core/api/reactive/RedisStringReactiveCommands.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2016 the original author or authors. + * Copyright 2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,13 +16,11 @@ package io.lettuce.core.api.reactive; import java.util.Map; - +import io.lettuce.core.output.KeyValueStreamingChannel; import io.lettuce.core.BitFieldArgs; import io.lettuce.core.KeyValue; import io.lettuce.core.SetArgs; import io.lettuce.core.Value; -import io.lettuce.core.output.KeyValueStreamingChannel; - import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -93,13 +91,30 @@ public interface RedisStringReactiveCommands { * * Basically the function consider the right of the string as padded with zeros if you look for clear bits and * specify no range or the start argument only. - * - * However this behavior changes if you are looking for clear bits and specify a range with both - * start and end. If no clear bit is found in the specified range, the function - * returns -1 as the user specified a clear range and there are no 0 bits in that range. */ Mono bitpos(K key, boolean state); + /** + * Find first bit set or clear in a string. + * + * @param key the key + * @param state the bit type: long + * @param start the start type: long + * @return Long integer-reply The command returns the position of the first bit set to 1 or 0 according to the request. + * + * If we look for set bits (the bit argument is 1) and the string is empty or composed of just zero bytes, -1 is + * returned. + * + * If we look for clear bits (the bit argument is 0) and the string only contains bit set to 1, the function returns + * the first bit not part of the string on the right. So if the string is tree bytes set to the value 0xff the + * command {@code BITPOS key 0} will return 24, since up to bit 23 all the bits are 1. + * + * Basically the function consider the right of the string as padded with zeros if you look for clear bits and + * specify no range or the start argument only. + * @since 5.0.1 + */ + Mono bitpos(K key, boolean state, long start); + /** * Find first bit set or clear in a string. * diff --git a/src/main/java/io/lettuce/core/api/sync/RedisStringCommands.java b/src/main/java/io/lettuce/core/api/sync/RedisStringCommands.java index 3601db0f4a..8ceea6670a 100644 --- a/src/main/java/io/lettuce/core/api/sync/RedisStringCommands.java +++ b/src/main/java/io/lettuce/core/api/sync/RedisStringCommands.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2016 the original author or authors. + * Copyright 2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,11 +17,13 @@ import java.util.List; import java.util.Map; - +import io.lettuce.core.output.KeyValueStreamingChannel; +import io.lettuce.core.output.ValueStreamingChannel; import io.lettuce.core.BitFieldArgs; import io.lettuce.core.KeyValue; import io.lettuce.core.SetArgs; -import io.lettuce.core.output.KeyValueStreamingChannel; +import io.lettuce.core.Value; +import reactor.core.publisher.Mono; /** * Synchronous executed commands for Strings. @@ -90,13 +92,30 @@ public interface RedisStringCommands { * * Basically the function consider the right of the string as padded with zeros if you look for clear bits and * specify no range or the start argument only. - * - * However this behavior changes if you are looking for clear bits and specify a range with both - * start and end. If no clear bit is found in the specified range, the function - * returns -1 as the user specified a clear range and there are no 0 bits in that range. */ Long bitpos(K key, boolean state); + /** + * Find first bit set or clear in a string. + * + * @param key the key + * @param state the bit type: long + * @param start the start type: long + * @return Long integer-reply The command returns the position of the first bit set to 1 or 0 according to the request. + * + * If we look for set bits (the bit argument is 1) and the string is empty or composed of just zero bytes, -1 is + * returned. + * + * If we look for clear bits (the bit argument is 0) and the string only contains bit set to 1, the function returns + * the first bit not part of the string on the right. So if the string is tree bytes set to the value 0xff the + * command {@code BITPOS key 0} will return 24, since up to bit 23 all the bits are 1. + * + * Basically the function consider the right of the string as padded with zeros if you look for clear bits and + * specify no range or the start argument only. + * @since 5.0.1 + */ + Long bitpos(K key, boolean state, long start); + /** * Find first bit set or clear in a string. * diff --git a/src/main/java/io/lettuce/core/cluster/api/async/NodeSelectionStringAsyncCommands.java b/src/main/java/io/lettuce/core/cluster/api/async/NodeSelectionStringAsyncCommands.java index f60a119346..f592160533 100644 --- a/src/main/java/io/lettuce/core/cluster/api/async/NodeSelectionStringAsyncCommands.java +++ b/src/main/java/io/lettuce/core/cluster/api/async/NodeSelectionStringAsyncCommands.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2016 the original author or authors. + * Copyright 2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,11 +17,14 @@ import java.util.List; import java.util.Map; - +import io.lettuce.core.output.KeyValueStreamingChannel; +import io.lettuce.core.output.ValueStreamingChannel; import io.lettuce.core.BitFieldArgs; import io.lettuce.core.KeyValue; import io.lettuce.core.SetArgs; -import io.lettuce.core.output.KeyValueStreamingChannel; +import io.lettuce.core.Value; +import io.lettuce.core.RedisFuture; +import reactor.core.publisher.Mono; /** * Asynchronous executed commands on a node selection for Strings. @@ -90,13 +93,30 @@ public interface NodeSelectionStringAsyncCommands { * * Basically the function consider the right of the string as padded with zeros if you look for clear bits and * specify no range or the start argument only. - * - * However this behavior changes if you are looking for clear bits and specify a range with both - * start and end. If no clear bit is found in the specified range, the function - * returns -1 as the user specified a clear range and there are no 0 bits in that range. */ AsyncExecutions bitpos(K key, boolean state); + /** + * Find first bit set or clear in a string. + * + * @param key the key + * @param state the bit type: long + * @param start the start type: long + * @return Long integer-reply The command returns the position of the first bit set to 1 or 0 according to the request. + * + * If we look for set bits (the bit argument is 1) and the string is empty or composed of just zero bytes, -1 is + * returned. + * + * If we look for clear bits (the bit argument is 0) and the string only contains bit set to 1, the function returns + * the first bit not part of the string on the right. So if the string is tree bytes set to the value 0xff the + * command {@code BITPOS key 0} will return 24, since up to bit 23 all the bits are 1. + * + * Basically the function consider the right of the string as padded with zeros if you look for clear bits and + * specify no range or the start argument only. + * @since 5.0.1 + */ + AsyncExecutions bitpos(K key, boolean state, long start); + /** * Find first bit set or clear in a string. * diff --git a/src/main/java/io/lettuce/core/cluster/api/sync/NodeSelectionStringCommands.java b/src/main/java/io/lettuce/core/cluster/api/sync/NodeSelectionStringCommands.java index 7ec226380a..d1611df66e 100644 --- a/src/main/java/io/lettuce/core/cluster/api/sync/NodeSelectionStringCommands.java +++ b/src/main/java/io/lettuce/core/cluster/api/sync/NodeSelectionStringCommands.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2016 the original author or authors. + * Copyright 2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,11 +17,13 @@ import java.util.List; import java.util.Map; - +import io.lettuce.core.output.KeyValueStreamingChannel; +import io.lettuce.core.output.ValueStreamingChannel; import io.lettuce.core.BitFieldArgs; import io.lettuce.core.KeyValue; import io.lettuce.core.SetArgs; -import io.lettuce.core.output.KeyValueStreamingChannel; +import io.lettuce.core.Value; +import reactor.core.publisher.Mono; /** * Synchronous executed commands on a node selection for Strings. @@ -90,13 +92,30 @@ public interface NodeSelectionStringCommands { * * Basically the function consider the right of the string as padded with zeros if you look for clear bits and * specify no range or the start argument only. - * - * However this behavior changes if you are looking for clear bits and specify a range with both - * start and end. If no clear bit is found in the specified range, the function - * returns -1 as the user specified a clear range and there are no 0 bits in that range. */ Executions bitpos(K key, boolean state); + /** + * Find first bit set or clear in a string. + * + * @param key the key + * @param state the bit type: long + * @param start the start type: long + * @return Long integer-reply The command returns the position of the first bit set to 1 or 0 according to the request. + * + * If we look for set bits (the bit argument is 1) and the string is empty or composed of just zero bytes, -1 is + * returned. + * + * If we look for clear bits (the bit argument is 0) and the string only contains bit set to 1, the function returns + * the first bit not part of the string on the right. So if the string is tree bytes set to the value 0xff the + * command {@code BITPOS key 0} will return 24, since up to bit 23 all the bits are 1. + * + * Basically the function consider the right of the string as padded with zeros if you look for clear bits and + * specify no range or the start argument only. + * @since 5.0.1 + */ + Executions bitpos(K key, boolean state, long start); + /** * Find first bit set or clear in a string. * diff --git a/src/main/templates/io/lettuce/core/api/RedisStringCommands.java b/src/main/templates/io/lettuce/core/api/RedisStringCommands.java index 5baf4752f7..76c04da110 100644 --- a/src/main/templates/io/lettuce/core/api/RedisStringCommands.java +++ b/src/main/templates/io/lettuce/core/api/RedisStringCommands.java @@ -91,13 +91,30 @@ public interface RedisStringCommands { * * Basically the function consider the right of the string as padded with zeros if you look for clear bits and * specify no range or the start argument only. - * - * However this behavior changes if you are looking for clear bits and specify a range with both - * start and end. If no clear bit is found in the specified range, the function - * returns -1 as the user specified a clear range and there are no 0 bits in that range. */ Long bitpos(K key, boolean state); + /** + * Find first bit set or clear in a string. + * + * @param key the key + * @param state the bit type: long + * @param start the start type: long + * @return Long integer-reply The command returns the position of the first bit set to 1 or 0 according to the request. + * + * If we look for set bits (the bit argument is 1) and the string is empty or composed of just zero bytes, -1 is + * returned. + * + * If we look for clear bits (the bit argument is 0) and the string only contains bit set to 1, the function returns + * the first bit not part of the string on the right. So if the string is tree bytes set to the value 0xff the + * command {@code BITPOS key 0} will return 24, since up to bit 23 all the bits are 1. + * + * Basically the function consider the right of the string as padded with zeros if you look for clear bits and + * specify no range or the start argument only. + * @since 5.0.1 + */ + Long bitpos(K key, boolean state, long start); + /** * Find first bit set or clear in a string. * diff --git a/src/test/java/io/lettuce/apigenerator/CreateAsyncApi.java b/src/test/java/io/lettuce/apigenerator/CreateAsyncApi.java index 5edc38a276..24cbf927b9 100644 --- a/src/test/java/io/lettuce/apigenerator/CreateAsyncApi.java +++ b/src/test/java/io/lettuce/apigenerator/CreateAsyncApi.java @@ -66,7 +66,7 @@ public CreateAsyncApi(String templateName) { String targetName = templateName.replace("Commands", "AsyncCommands"); - File templateFile = new File(Constants.TEMPLATES, "com/lambdaworks/redis/api/" + templateName + ".java"); + File templateFile = new File(Constants.TEMPLATES, "io/lettuce/core/api/" + templateName + ".java"); String targetPackage; if (templateName.contains("RedisSentinel")) { diff --git a/src/test/java/io/lettuce/apigenerator/CreateAsyncNodeSelectionClusterApi.java b/src/test/java/io/lettuce/apigenerator/CreateAsyncNodeSelectionClusterApi.java index c2177c4c6c..e55ce7b2df 100644 --- a/src/test/java/io/lettuce/apigenerator/CreateAsyncNodeSelectionClusterApi.java +++ b/src/test/java/io/lettuce/apigenerator/CreateAsyncNodeSelectionClusterApi.java @@ -69,7 +69,7 @@ public static List arguments() { public CreateAsyncNodeSelectionClusterApi(String templateName) { String targetName = templateName.replace("Commands", "AsyncCommands").replace("Redis", "NodeSelection"); - File templateFile = new File(Constants.TEMPLATES, "com/lambdaworks/redis/api/" + templateName + ".java"); + File templateFile = new File(Constants.TEMPLATES, "io/lettuce/core/api/" + templateName + ".java"); String targetPackage = "io.lettuce.core.cluster.api.async"; factory = new CompilationUnitFactory(templateFile, Constants.SOURCES, targetPackage, targetName, commentMutator(), diff --git a/src/test/java/io/lettuce/apigenerator/CreateReactiveApi.java b/src/test/java/io/lettuce/apigenerator/CreateReactiveApi.java index 2eecf76a80..269e1820f7 100644 --- a/src/test/java/io/lettuce/apigenerator/CreateReactiveApi.java +++ b/src/test/java/io/lettuce/apigenerator/CreateReactiveApi.java @@ -76,7 +76,7 @@ public static List arguments() { public CreateReactiveApi(String templateName) { String targetName = templateName.replace("Commands", "ReactiveCommands"); - File templateFile = new File(Constants.TEMPLATES, "com/lambdaworks/redis/api/" + templateName + ".java"); + File templateFile = new File(Constants.TEMPLATES, "io/lettuce/core/api/" + templateName + ".java"); String targetPackage; if (templateName.contains("RedisSentinel")) { diff --git a/src/test/java/io/lettuce/apigenerator/CreateSyncApi.java b/src/test/java/io/lettuce/apigenerator/CreateSyncApi.java index 06d19c6fd5..3b84a1bde0 100644 --- a/src/test/java/io/lettuce/apigenerator/CreateSyncApi.java +++ b/src/test/java/io/lettuce/apigenerator/CreateSyncApi.java @@ -64,7 +64,7 @@ public static List arguments() { public CreateSyncApi(String templateName) { String targetName = templateName; - File templateFile = new File(Constants.TEMPLATES, "com/lambdaworks/redis/api/" + templateName + ".java"); + File templateFile = new File(Constants.TEMPLATES, "io/lettuce/core/api/" + templateName + ".java"); String targetPackage; if (templateName.contains("RedisSentinel")) { diff --git a/src/test/java/io/lettuce/apigenerator/CreateSyncNodeSelectionClusterApi.java b/src/test/java/io/lettuce/apigenerator/CreateSyncNodeSelectionClusterApi.java index 19cc29ecb8..041a947be5 100644 --- a/src/test/java/io/lettuce/apigenerator/CreateSyncNodeSelectionClusterApi.java +++ b/src/test/java/io/lettuce/apigenerator/CreateSyncNodeSelectionClusterApi.java @@ -69,7 +69,7 @@ public static List arguments() { public CreateSyncNodeSelectionClusterApi(String templateName) { String targetName = templateName.replace("Redis", "NodeSelection"); - File templateFile = new File(Constants.TEMPLATES, "com/lambdaworks/redis/api/" + templateName + ".java"); + File templateFile = new File(Constants.TEMPLATES, "io/lettuce/core/api/" + templateName + ".java"); String targetPackage = "io.lettuce.core.cluster.api.sync"; // todo: remove AutoCloseable from BaseNodeSelectionAsyncCommands diff --git a/src/test/java/io/lettuce/core/commands/BitCommandTest.java b/src/test/java/io/lettuce/core/commands/BitCommandTest.java index 26186d0d43..23c0cbe40f 100644 --- a/src/test/java/io/lettuce/core/commands/BitCommandTest.java +++ b/src/test/java/io/lettuce/core/commands/BitCommandTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2016 the original author or authors. + * Copyright 2011-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -212,11 +212,13 @@ public void bitposOffset() throws Exception { redis.setbit(key, 3, 0); redis.setbit(key, 4, 0); redis.setbit(key, 5, 1); + redis.setbit(key, 16, 1); assertThat((long) bitstring.getbit(key, 1)).isEqualTo(1); assertThat((long) bitstring.getbit(key, 4)).isEqualTo(0); assertThat((long) bitstring.getbit(key, 5)).isEqualTo(1); - assertThat(bitstring.get(key)).isEqualTo("00100011"); + assertThat(bitstring.get(key)).isEqualTo("001000110000000000000001"); + assertThat((long) redis.bitpos(key, true, 1)).isEqualTo(16); assertThat((long) redis.bitpos(key, false, 0, 0)).isEqualTo(2); }