From c4b9d94c339533fe4b42be8e4161f1433b1f7b81 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Thu, 31 Mar 2016 16:39:39 +0200 Subject: [PATCH 1/2] Use CharsetDecoder to decode a DataBuffer into a String. --- .../core/codec/support/StringDecoder.java | 13 ++++++++++--- .../core/codec/support/StringDecoderTests.java | 11 +++++++++++ 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/spring-web-reactive/src/main/java/org/springframework/core/codec/support/StringDecoder.java b/spring-web-reactive/src/main/java/org/springframework/core/codec/support/StringDecoder.java index 51fc665aa9..a72e4249fb 100644 --- a/spring-web-reactive/src/main/java/org/springframework/core/codec/support/StringDecoder.java +++ b/spring-web-reactive/src/main/java/org/springframework/core/codec/support/StringDecoder.java @@ -16,6 +16,7 @@ package org.springframework.core.codec.support; +import java.nio.CharBuffer; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; @@ -38,11 +39,13 @@ import org.springframework.util.MimeType; * @author Sebastien Deleuze * @author Brian Clozel * @author Arjen Poutsma + * @author Mark Paluch * @see StringEncoder */ public class StringDecoder extends AbstractDecoder { public static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8; + public static final String EMPTY = ""; private final boolean reduceToSingleBuffer; @@ -82,9 +85,13 @@ public class StringDecoder extends AbstractDecoder { } Charset charset = getCharset(mimeType); return inputFlux.map(content -> { - byte[] bytes = new byte[content.readableByteCount()]; - content.read(bytes); - return new String(bytes, charset); + // fast-path exit. + if(content.readableByteCount() == 0) { + return EMPTY; + } + + CharBuffer charBuffer = charset.decode(content.asByteBuffer()); + return charBuffer.toString(); }); } diff --git a/spring-web-reactive/src/test/java/org/springframework/core/codec/support/StringDecoderTests.java b/spring-web-reactive/src/test/java/org/springframework/core/codec/support/StringDecoderTests.java index d8494312b9..4195dc4052 100644 --- a/spring-web-reactive/src/test/java/org/springframework/core/codec/support/StringDecoderTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/core/codec/support/StringDecoderTests.java @@ -33,6 +33,7 @@ import static org.junit.Assert.*; /** * @author Sebastien Deleuze * @author Brian Clozel + * @author Mark Paluch */ public class StringDecoderTests extends AbstractAllocatingTestCase { @@ -92,4 +93,14 @@ public class StringDecoderTests extends AbstractAllocatingTestCase { assertEquals("foobar", result); } + @Test + public void decodeEmpty() throws InterruptedException { + Flux source = Flux.just(stringBuffer("")); + Single single = RxJava1SingleConverter.from(this.decoder.decode(source, + ResolvableType.forClassWithGenerics(Single.class, String.class), + MediaType.TEXT_PLAIN)); + String result = single.toBlocking().value(); + assertEquals("", result); + } + } From 9e79b344ca02c7dd04d59f5c7567e29947b79c22 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Mon, 4 Apr 2016 09:49:22 +0200 Subject: [PATCH 2/2] Implement review feedback. Remove empty string optimization. Simplify test to use only Mono/Flux/TestSubscriber instead of mixing with RxJava. --- .../core/codec/support/StringDecoder.java | 6 ------ .../core/codec/support/StringDecoderTests.java | 11 +++++------ 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/spring-web-reactive/src/main/java/org/springframework/core/codec/support/StringDecoder.java b/spring-web-reactive/src/main/java/org/springframework/core/codec/support/StringDecoder.java index a72e4249fb..56ac1d9f46 100644 --- a/spring-web-reactive/src/main/java/org/springframework/core/codec/support/StringDecoder.java +++ b/spring-web-reactive/src/main/java/org/springframework/core/codec/support/StringDecoder.java @@ -45,7 +45,6 @@ import org.springframework.util.MimeType; public class StringDecoder extends AbstractDecoder { public static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8; - public static final String EMPTY = ""; private final boolean reduceToSingleBuffer; @@ -85,11 +84,6 @@ public class StringDecoder extends AbstractDecoder { } Charset charset = getCharset(mimeType); return inputFlux.map(content -> { - // fast-path exit. - if(content.readableByteCount() == 0) { - return EMPTY; - } - CharBuffer charBuffer = charset.decode(content.asByteBuffer()); return charBuffer.toString(); }); diff --git a/spring-web-reactive/src/test/java/org/springframework/core/codec/support/StringDecoderTests.java b/spring-web-reactive/src/test/java/org/springframework/core/codec/support/StringDecoderTests.java index 4195dc4052..0901d5bca0 100644 --- a/spring-web-reactive/src/test/java/org/springframework/core/codec/support/StringDecoderTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/core/codec/support/StringDecoderTests.java @@ -95,12 +95,11 @@ public class StringDecoderTests extends AbstractAllocatingTestCase { @Test public void decodeEmpty() throws InterruptedException { - Flux source = Flux.just(stringBuffer("")); - Single single = RxJava1SingleConverter.from(this.decoder.decode(source, - ResolvableType.forClassWithGenerics(Single.class, String.class), - MediaType.TEXT_PLAIN)); - String result = single.toBlocking().value(); - assertEquals("", result); + Mono source = Mono.just(stringBuffer("")); + Flux output = + this.decoder.decode(source, ResolvableType.forClass(String.class), null); + TestSubscriber testSubscriber = new TestSubscriber<>(); + testSubscriber.bindTo(output).assertValues(""); } }