Move SSD response stream selection to typed Kotlin

ober

c20a525d81bc76ba7f600fe8ea1cf088c64085d5

diff --git a/templates/ssd-review.ss b/templates/ssd-review.ss
index 7b91e97..470f581 100644
--- a/templates/ssd-review.ss
+++ b/templates/ssd-review.ss
@@ -5389,9 +5389,18 @@
               (nullable-none String))))))
 
     (typed-kotlin-file "com/sfb/ssdreview/NetworkSafety.kt"
+      (kotlin-imports (java io InputStream)
+                      (java io BufferedInputStream)
+                      (java util zip GZIPInputStream))
       (typed-library (com sfb ssdreview)
         (export normalizeRemoteEndpointValue normalizeRemoteEndpoint urlEncode
-                contentEncodingIsGzip localTruthHttpAllowed)
+                contentEncodingIsGzip responseInputStream
+                localTruthHttpAllowed)
+        (type InputStream)
+        (extern (bufferedInputStream (input : InputStream)) : InputStream
+          (kotlin-call java io BufferedInputStream))
+        (extern (gzipInputStream (input : InputStream)) : InputStream
+          (kotlin-call java util zip GZIPInputStream))
         (def (normalizeRemoteEndpointValue (value : String) (defaultEndpoint : String)) : String
           (let ((trimmed (string-trim value)))
             (let ((base (if (string-blank? trimmed) defaultEndpoint trimmed)))
@@ -5414,6 +5423,11 @@
           (url-encode-utf8 value))
         (def (contentEncodingIsGzip (value : String)) : Bool
           (string-contains? (string-lowercase value) "gzip"))
+        (def (responseInputStream (raw : InputStream)
+                                  (contentEncoding : String)) : InputStream
+          (if (contentEncodingIsGzip contentEncoding)
+              (gzipInputStream (bufferedInputStream raw))
+              raw))
         (def (localTruthHttpAllowed (host : String)) : Bool
           (let ((lower (string-lowercase host)))
             (if (or (or (equal? lower "localhost")
@@ -8213,11 +8227,7 @@
        "            throw IllegalStateException(\"HTTP response exceeds compressed-byte limit\")"
        "        }"
        "        val raw = LimitedInputStream(connection.inputStream, MAX_HTTP_COMPRESSED_BYTES)"
-       "        val input = if (contentEncodingIsGzip(connection.contentEncoding ?: \"\")) {"
-       "            GZIPInputStream(BufferedInputStream(raw))"
-       "        } else {"
-       "            raw"
-       "        }"
+       "        val input = responseInputStream(raw, connection.contentEncoding ?: \"\")"
        "        return input.use { readBoundedBytes(it, MAX_HTTP_TEXT_BYTES).decodeToString() }"
        "    }"
        ""