Generate SSD remote response reader from typed Jerboa

ober

104f67c02961140e265f04fad1ecaf65ba1220be

diff --git a/templates/ssd-review.ss b/templates/ssd-review.ss
index 130b813..9299f74 100644
--- a/templates/ssd-review.ss
+++ b/templates/ssd-review.ss
@@ -15537,6 +15537,7 @@
                       (java nio file LinkOption)
                       (java nio file Path)
                       (java security MessageDigest)
+                      (javax net ssl HttpsURLConnection)
                       (org json JSONObject))
       (typed-library (com sfb ssdreview)
         (export truthStoreSha256Hex truthStoreContainedLeaf
@@ -15547,13 +15548,15 @@
                 truthStoreStorageStatsLocal
                 truthStoreEnsureStorageCapacityLocal
                 truthStoreLoadRemoteConfigLocal
-                truthStoreRemoteUrlLocal)
+                truthStoreRemoteUrlLocal
+                truthStoreReadResponseTextLocal)
         (type Context)
         (type Exception)
         (type File)
         (type InputStream)
         (type Int32)
         (type LinkOption)
+        (type HttpsURLConnection)
         (type MessageDigest)
         (type Path)
         (type RemoteConfig)
@@ -15585,6 +15588,19 @@
                   (file : File)
                   (json : JSONObject)) : Unit
           (kotlin-member-call appendJsonLine))
+        (extern (truthStoreConnectionInputStream
+                  (connection : HttpsURLConnection)) : InputStream
+          (kotlin-member-get inputStream))
+        (extern (truthStoreConnectionContentEncoding
+                  (connection : HttpsURLConnection)) : (Nullable String)
+          (kotlin-member-get contentEncoding))
+        (extern (truthStoreConnectionContentLength
+                  (connection : HttpsURLConnection)) : Int
+          (kotlin-member-get contentLengthLong))
+        (extern (truthStoreLimitedInputStream
+                  (input : InputStream)
+                  (limit : Int)) : InputStream
+          (kotlin-call LimitedInputStream))
         (extern (truthStoreContextModePrivate) : Int32
           (kotlin-value Context MODE_PRIVATE))
         (extern (truthStoreSharedPreferences
@@ -15660,6 +15676,10 @@
           (kotlin-member-call digest))
         (extern (truthStoreMaxZipEntryBytes) : Int
           (kotlin-value MAX_ZIP_ENTRY_BYTES))
+        (extern (truthStoreMaxHttpTextBytes) : Int
+          (kotlin-value MAX_HTTP_TEXT_BYTES))
+        (extern (truthStoreMaxHttpCompressedBytes) : Int
+          (kotlin-value MAX_HTTP_COMPRESSED_BYTES))
         (extern (truthStoreMaxStorageBytes) : Int
           (kotlin-value MAX_STORAGE_BYTES))
         (extern (truthStoreMaxStorageFiles) : Int32
@@ -15992,7 +16012,33 @@
                           (RemoteConfig-apiUrl config))
                         basePort)
                       "Remote URL escaped configured HTTPS origin")
-                    candidate))))))))
+                    candidate))))))
+        (def (truthStoreReadResponseTextLocal
+               (connection : HttpsURLConnection)) : String
+          (begin
+            (if (> (truthStoreConnectionContentLength connection)
+                   (truthStoreMaxHttpCompressedBytes))
+              (throw
+                (truthStoreIllegalStateException
+                  "HTTP response exceeds compressed-byte limit")
+                Unit)
+              (begin))
+            (let ((raw
+                    (truthStoreLimitedInputStream
+                      (truthStoreConnectionInputStream connection)
+                      (truthStoreMaxHttpCompressedBytes))))
+              (let ((input
+                      (responseInputStream
+                        raw
+                        (nullableTextOrEmpty
+                          (truthStoreConnectionContentEncoding
+                            connection)))))
+                (try-finally
+                  (utf8->string
+                    (readBoundedBytes
+                      input
+                      (truthStoreMaxHttpTextBytes)))
+                  (truthStoreInputStreamClose input))))))))
 
     (kotlin-file-lines "com/sfb/ssdreview/TruthStore.kt"
       (
@@ -16276,14 +16322,8 @@
        "        }"
        "    }"
        ""
-       "    private fun readResponseText(connection: HttpsURLConnection): String {"
-       "        if (connectionContentLengthExceedsLimit(connection, MAX_HTTP_COMPRESSED_BYTES)) {"
-       "            throw IllegalStateException(\"HTTP response exceeds compressed-byte limit\")"
-       "        }"
-       "        val raw = LimitedInputStream(connection.inputStream, MAX_HTTP_COMPRESSED_BYTES)"
-       "        val input = responseInputStream(raw, nullableTextOrEmpty(connection.contentEncoding))"
-       "        return input.use { readBoundedBytes(it, MAX_HTTP_TEXT_BYTES).decodeToString() }"
-       "    }"
+       "    private fun readResponseText(connection: HttpsURLConnection): String ="
+       "        truthStoreReadResponseTextLocal(connection)"
        ""
        "    private fun writeRemoteTruth("
        "        truth: JSONObject,"
diff --git a/tests/ssd-security-test.sh b/tests/ssd-security-test.sh
index 8d24958..4633fdd 100755
--- a/tests/ssd-security-test.sh
+++ b/tests/ssd-security-test.sh
@@ -58,7 +58,7 @@ require_generated_text 'textUtf8Bytes(key)'
 require_text 'StandardCopyOption.ATOMIC_MOVE'
 require_text 'LinkOption.NOFOLLOW_LINKS'
 require_text 'LimitedInputStream(input, MAX_REMOTE_ZIP_BYTES)'
-require_text 'LimitedInputStream(connection.inputStream, MAX_HTTP_COMPRESSED_BYTES)'
+require_generated_text 'LimitedInputStream(connection.inputStream, MAX_HTTP_COMPRESSED_BYTES)'
 require_generated_text 'MAX_HTTP_COMPRESSED_BYTES: Long = ((2L * 1024L) * 1024L)'
 require_generated_text 'MAX_ZIP_ENTRY_BYTES: Long = ((4L * 1024L) * 1024L)'
 require_generated_text 'MAX_ZIP_TOTAL_BYTES: Long = ((64L * 1024L) * 1024L)'