diff --git a/src/main/java/io/lettuce/core/codec/StringCodec.java b/src/main/java/io/lettuce/core/codec/StringCodec.java index af64835e34..db9eda9ebd 100644 --- a/src/main/java/io/lettuce/core/codec/StringCodec.java +++ b/src/main/java/io/lettuce/core/codec/StringCodec.java @@ -17,7 +17,11 @@ import java.nio.ByteBuffer; import java.nio.CharBuffer; -import java.nio.charset.*; +import java.nio.charset.CharacterCodingException; +import java.nio.charset.Charset; +import java.nio.charset.CharsetEncoder; +import java.nio.charset.CoderResult; +import java.nio.charset.StandardCharsets; import io.lettuce.core.internal.LettuceAssert; import io.netty.buffer.ByteBuf; @@ -100,6 +104,16 @@ public int estimateSize(Object keyOrValue) { return 0; } + @Override + public boolean isEstimateExact() { + + if (ascii) { + return true; + } + + return ToByteBufEncoder.super.isEstimateExact(); + } + @Override public void encodeValue(String value, ByteBuf target) { encode(value, target); @@ -186,8 +200,8 @@ public void encode(String str, ByteBuf target) { } /** - * Calculate either the maximum number of bytes a string may occupy in a given character set or - * the average number of bytes it may hold. + * Calculate either the maximum number of bytes a string may occupy in a given character set or the average number of bytes + * it may hold. */ int sizeOf(String value, boolean estimate) { @@ -205,4 +219,5 @@ int sizeOf(String value, boolean estimate) { return (int) maxBytesPerChar * value.length(); } + } diff --git a/src/main/java/io/lettuce/core/codec/ToByteBufEncoder.java b/src/main/java/io/lettuce/core/codec/ToByteBufEncoder.java index beedc8cd34..c3faea4596 100644 --- a/src/main/java/io/lettuce/core/codec/ToByteBufEncoder.java +++ b/src/main/java/io/lettuce/core/codec/ToByteBufEncoder.java @@ -58,10 +58,11 @@ public interface ToByteBufEncoder { int estimateSize(Object keyOrValue); /** - * Returns true if {@link ToByteBufEncoder#estimateSize(Object)} returns exact size - * This is used as an optimisation to reduce memory allocations when encoding data + * Returns {@code true} if {@link #estimateSize(Object)} returns exact size This is used as an optimization to reduce memory + * allocations when encoding data. * - * @return true if {@link ToByteBufEncoder#estimateSize(Object)} returns exact size + * @return {@code true} if {@link #estimateSize(Object)} returns exact size. + * @since 6.3.2 */ default boolean isEstimateExact() { return false; diff --git a/src/main/java/io/lettuce/core/protocol/CommandArgs.java b/src/main/java/io/lettuce/core/protocol/CommandArgs.java index 3563bbaab2..b32b8edaa6 100644 --- a/src/main/java/io/lettuce/core/protocol/CommandArgs.java +++ b/src/main/java/io/lettuce/core/protocol/CommandArgs.java @@ -547,9 +547,9 @@ static void writeInteger(ByteBuf target, long value) { static class IntegerCache { - static final IntegerArgument cache[]; + static final IntegerArgument[] cache; - static final IntegerArgument negativeCache[]; + static final IntegerArgument[] negativeCache; static { int high = Integer.getInteger("io.lettuce.core.CommandArgs.IntegerCache", 128); @@ -648,8 +648,8 @@ static void writeString(ByteBuf target, char[] value) { IntegerArgument.writeInteger(target, value.length); target.writeBytes(CRLF); - for (int i = 0; i < value.length; i++) { - target.writeByte((byte) value[i]); + for (char c : value) { + target.writeByte((byte) c); } target.writeBytes(CRLF); } @@ -681,29 +681,7 @@ static KeyArgument of(K key, RedisCodec codec) { void encode(ByteBuf target) { if (codec instanceof ToByteBufEncoder) { - - ToByteBufEncoder toByteBufEncoder = (ToByteBufEncoder) codec; - - if (toByteBufEncoder.isEstimateExact()) { - target.writeByte('$'); - - IntegerArgument.writeInteger(target, toByteBufEncoder.estimateSize(key)); - target.writeBytes(CRLF); - - toByteBufEncoder.encodeKey(key, target); - target.writeBytes(CRLF); - } else { - ByteBuf temporaryBuffer = target.alloc().buffer(toByteBufEncoder.estimateSize(key) + 6); - - try { - - toByteBufEncoder.encodeKey(key, temporaryBuffer); - ByteBufferArgument.writeByteBuf(target, temporaryBuffer); - } finally { - temporaryBuffer.release(); - } - } - + CommandArgs.encode(target, (ToByteBufEncoder) codec, key, ToByteBufEncoder::encodeKey); return; } @@ -737,27 +715,7 @@ static ValueArgument of(V val, RedisCodec codec) { void encode(ByteBuf target) { if (codec instanceof ToByteBufEncoder) { - - ToByteBufEncoder toByteBufEncoder = (ToByteBufEncoder) codec; - if (toByteBufEncoder.isEstimateExact()) { - target.writeByte('$'); - - IntegerArgument.writeInteger(target, toByteBufEncoder.estimateSize(val)); - target.writeBytes(CRLF); - - toByteBufEncoder.encodeValue(val, target); - target.writeBytes(CRLF); - } else { - ByteBuf temporaryBuffer = target.alloc().buffer(toByteBufEncoder.estimateSize(val) + 6); - - try { - toByteBufEncoder.encodeValue(val, temporaryBuffer); - ByteBufferArgument.writeByteBuf(target, temporaryBuffer); - } finally { - temporaryBuffer.release(); - } - } - + CommandArgs.encode(target, (ToByteBufEncoder) codec, val, ToByteBufEncoder::encodeValue); return; } @@ -771,4 +729,33 @@ public String toString() { } + static void encode(ByteBuf target, ToByteBufEncoder encoder, T item, EncodeFunction encodeFunction) { + + if (encoder.isEstimateExact()) { + + target.writeByte('$'); + IntegerArgument.writeInteger(target, encoder.estimateSize(item)); + target.writeBytes(CRLF); + + encodeFunction.encode(encoder, item, target); + target.writeBytes(CRLF); + } else { + + ByteBuf temporaryBuffer = target.alloc().buffer(encoder.estimateSize(item) + 6); + + try { + encodeFunction.encode(encoder, item, temporaryBuffer); + ByteBufferArgument.writeByteBuf(target, temporaryBuffer); + } finally { + temporaryBuffer.release(); + } + } + } + + interface EncodeFunction { + + void encode(ToByteBufEncoder encoder, T item, ByteBuf target); + + } + }