From dd9db975606c39c8cb9b691ee81aa1c5982aa628 Mon Sep 17 00:00:00 2001 From: Ferdinand Svehla Date: Wed, 15 Sep 2021 10:02:55 +0200 Subject: [PATCH] Fix transducer handling of empty arrays --- .../zio/json/JsonDecoderPlatformSpecific.scala | 16 +++++++++++++--- .../zio/json/DecoderPlatformSpecificSpec.scala | 9 +++++++++ 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/zio-json/jvm/src/main/scala/zio/json/JsonDecoderPlatformSpecific.scala b/zio-json/jvm/src/main/scala/zio/json/JsonDecoderPlatformSpecific.scala index a114f247a..591ef0d42 100644 --- a/zio-json/jvm/src/main/scala/zio/json/JsonDecoderPlatformSpecific.scala +++ b/zio-json/jvm/src/main/scala/zio/json/JsonDecoderPlatformSpecific.scala @@ -53,12 +53,12 @@ trait JsonDecoderPlatformSpecific[A] { self: JsonDecoder[A] => ZTransducer { for { // format: off - runtime <- ZIO.runtime[Any].toManaged_ + runtime <- ZManaged.runtime[Any] inQueue <- Queue.unbounded[Take[Nothing, Char]].toManaged_ outQueue <- Queue.unbounded[Take[Throwable, A]].toManaged_ ended <- Ref.makeManaged(false) reader <- ZManaged.fromAutoCloseable { - ZIO.effectTotal { + UIO { def readPull: Iterator[Chunk[Char]] = runtime.unsafeRun(inQueue.take) .fold( @@ -70,13 +70,23 @@ trait JsonDecoderPlatformSpecific[A] { self: JsonDecoder[A] => new zio.stream.internal.ZReader(Iterator.empty ++ readPull) } } - jsonReader <- ZManaged.fromAutoCloseable(ZIO.effectTotal(new WithRetractReader(reader))) + jsonReader <- ZManaged.fromAutoCloseable(UIO(new WithRetractReader(reader))) process <- effectBlockingInterrupt { // Exceptions fall through and are pushed into the queue @tailrec def loop(atBeginning: Boolean): Unit = { val nextElem = try { if (atBeginning && delimiter == JsonStreamDelimiter.Array) { Lexer.char(Nil, jsonReader, '[') + + jsonReader.nextNonWhitespace() match { + case ']' => + // returning empty here instead of falling through, which would + // attempt to decode a value that we know doesn’t exist. + return () + + case _ => + jsonReader.retract() + } } else { delimiter match { case JsonStreamDelimiter.Newline => diff --git a/zio-json/jvm/src/test/scala-2/zio/json/DecoderPlatformSpecificSpec.scala b/zio-json/jvm/src/test/scala-2/zio/json/DecoderPlatformSpecificSpec.scala index f2b8f2b8d..9afa13584 100644 --- a/zio-json/jvm/src/test/scala-2/zio/json/DecoderPlatformSpecificSpec.scala +++ b/zio-json/jvm/src/test/scala-2/zio/json/DecoderPlatformSpecificSpec.scala @@ -197,6 +197,15 @@ object DecoderPlatformSpecificSpec extends DefaultRunnableSpec { assert(xs)(equalTo(Chunk(1001))) } }, + testM("empty array") { + ZStream + .fromIterable("[]".toSeq) + .transduce(JsonDecoder[String].decodeJsonTransducer(JsonStreamDelimiter.Array)) + .runCollect + .map { xs => + assert(xs)(isEmpty) + } + }, testM("decodes multiple elements") { ZStream .fromIterable("[ 1001, 1002, 1003 ]".toSeq)