clarified signature;
authorwenzelm
Fri, 21 Oct 2022 21:39:38 +0200
changeset 76358 cff0828c374f
parent 76357 49463aef2ead
child 76360 2b204e11141c
child 76361 3b9f36ef7365
clarified signature; more direct Zstd compression using arrays instead of streams;
src/Pure/General/bytes.scala
--- a/src/Pure/General/bytes.scala	Fri Oct 21 19:14:01 2022 +0200
+++ b/src/Pure/General/bytes.scala	Fri Oct 21 21:39:38 2022 +0200
@@ -192,7 +192,7 @@
 
   /* XZ / Zstd data compression */
 
-  private def detect_xz: Boolean =
+  def detect_xz: Boolean =
     length >= 6 &&
       bytes(offset)     == 0xFD.toByte &&
       bytes(offset + 1) == 0x37.toByte &&
@@ -201,46 +201,45 @@
       bytes(offset + 4) == 0x5A.toByte &&
       bytes(offset + 5) == 0x00.toByte
 
-  private def detect_zstd: Boolean =
+  def detect_zstd: Boolean =
     length >= 4 &&
       bytes(offset)     == 0x28.toByte &&
       bytes(offset + 1) == 0xB5.toByte &&
       bytes(offset + 2) == 0x2F.toByte &&
       bytes(offset + 3) == 0xFD.toByte
 
-  private def detect_error(name: String = ""): Nothing =
-    error("Cannot detect compression scheme" + (if (name.isEmpty) "" else " " + name))
+  def uncompress_xz(cache: Compress.Cache = Compress.Cache.none): Bytes =
+    using(new xz.XZInputStream(stream(), cache.for_xz))(Bytes.read_stream(_, hint = length))
+
+  def uncompress_zstd(cache: Compress.Cache = Compress.Cache.none): Bytes = {
+    Zstd.init()
+    val n = zstd.Zstd.decompressedSize(bytes, offset, length)
+    if (n > 0 && n < Integer.MAX_VALUE) {
+      Bytes(zstd.Zstd.decompress(array, n.toInt))
+    }
+    else {
+      using(new zstd.ZstdInputStream(stream(), cache.for_zstd))(Bytes.read_stream(_, hint = length))
+    }
+  }
 
   def uncompress(cache: Compress.Cache = Compress.Cache.none): Bytes =
-    using(
-      if (detect_xz) new xz.XZInputStream(stream(), cache.for_xz)
-      else if (detect_zstd) {
-        Zstd.init()
-        new zstd.ZstdInputStream(stream(), cache.for_zstd)
-      }
-      else detect_error()
-    )(Bytes.read_stream(_, hint = length))
-
-  def uncompress_xz(cache: Compress.Cache = Compress.Cache.none): Bytes =
-    if (detect_xz) uncompress(cache = cache) else detect_error("XZ")
-
-  def uncompress_zstd(cache: Compress.Cache = Compress.Cache.none): Bytes =
-    if (detect_zstd) uncompress(cache = cache) else detect_error("Zstd")
+    if (detect_xz) uncompress_xz(cache = cache)
+    else if (detect_zstd) uncompress_zstd(cache = cache)
+    else error("Cannot detect compression scheme")
 
   def compress(
     options: Compress.Options = Compress.Options(),
     cache: Compress.Cache = Compress.Cache.none
   ): Bytes = {
-    val result = new ByteArrayOutputStream(length)
-    using(
-      options match {
-        case options_xz: Compress.Options_XZ =>
-          new xz.XZOutputStream(result, options_xz.make, cache.for_xz)
-        case options_zstd: Compress.Options_Zstd =>
-          Zstd.init()
-          new zstd.ZstdOutputStream(result, cache.for_zstd, options_zstd.level)
-      })(write_stream)
-    new Bytes(result.toByteArray, 0, result.size)
+    options match {
+      case options_xz: Compress.Options_XZ =>
+        val result = new ByteArrayOutputStream(length)
+        using(new xz.XZOutputStream(result, options_xz.make, cache.for_xz))(write_stream)
+        new Bytes(result.toByteArray, 0, result.size)
+      case options_zstd: Compress.Options_Zstd =>
+        Zstd.init()
+        Bytes(zstd.Zstd.compress(array, options_zstd.level))
+    }
   }
 
   def maybe_compress(