diff --git a/http-core/src/main/scala/org/apache/pekko/http/impl/engine/http2/hpack/ByteStringInputStream.scala b/http-core/src/main/scala/org/apache/pekko/http/impl/engine/http2/hpack/ByteStringInputStream.scala index f3b3dc5a3..f0fb6fe0e 100644 --- a/http-core/src/main/scala/org/apache/pekko/http/impl/engine/http2/hpack/ByteStringInputStream.scala +++ b/http-core/src/main/scala/org/apache/pekko/http/impl/engine/http2/hpack/ByteStringInputStream.scala @@ -14,6 +14,9 @@ package org.apache.pekko.http.impl.engine.http2.hpack import java.io.{ ByteArrayInputStream, InputStream } +import java.lang.invoke.{ MethodHandles, MethodType } + +import scala.util.Try import org.apache.pekko import pekko.annotation.InternalApi @@ -24,10 +27,22 @@ import pekko.util.ByteString.ByteString1C @InternalApi private[http2] object ByteStringInputStream { + private lazy val byteStringInputStreamMethodTypeOpt = Try { + val lookup = MethodHandles.publicLookup() + val inputStreamMethodType = MethodType.methodType(classOf[InputStream]) + lookup.findVirtual(classOf[ByteString], "asInputStream", inputStreamMethodType) + }.toOption + def apply(bs: ByteString): InputStream = + byteStringInputStreamMethodTypeOpt.map { mh => + mh.invoke(bs).asInstanceOf[InputStream] + }.getOrElse { + legacyConvert(bs) + } + + private def legacyConvert(bs: ByteString): InputStream = bs match { case cs: ByteString1C => - // TODO optimise, ByteString needs to expose InputStream (esp if array backed, nice!) new ByteArrayInputStream(cs.toArrayUnsafe()) case _ => // NOTE: We actually measured recently, and compact + use array was pretty good usually