Generate limited SSD streams from typed Jerboa

ober

4078bbad5d296bfeb2d4891a22336bdcc1d191b6

diff --git a/templates/ssd-review.ss b/templates/ssd-review.ss
index 5c8b781..6a7664e 100644
--- a/templates/ssd-review.ss
+++ b/templates/ssd-review.ss
@@ -12502,6 +12502,115 @@
               (matrixPostTranslate imageMatrix offsetX offsetY)
               (matrixInvert imageMatrix inverse)
               (begin))))))
+
+    (typed-kotlin-file "com/sfb/ssdreview/LimitedStreams.kt"
+      (kotlin-imports (java io FilterInputStream)
+                      (java io FilterOutputStream)
+                      (java io InputStream)
+                      (java io OutputStream))
+      (typed-library (com sfb ssdreview)
+        (export LimitedInputStream LimitedOutputStream)
+        (type FilterInputStream)
+        (type FilterOutputStream)
+        (type InputStream)
+        (type OutputStream)
+        (type IllegalStateException)
+        (type Int32)
+        (type Bytes)
+        (extern (illegalStateException (message : String)) : IllegalStateException
+          (kotlin-call IllegalStateException))
+        (extern (superInputReadByte) : Int32
+          (kotlin-call super read))
+        (extern (superInputReadBuffer
+                  (buffer : Bytes)
+                  (offset : Int32)
+                  (length : Int32)) : Int32
+          (kotlin-call super read))
+        (extern (filterOutputStreamOut
+                  (stream : LimitedOutputStream)) : OutputStream
+          (kotlin-member-get out))
+        (extern (outputStreamWriteByte
+                  (output : OutputStream)
+                  (value : Int32)) : Unit
+          (kotlin-member-call write))
+        (extern (outputStreamWriteBuffer
+                  (output : OutputStream)
+                  (buffer : Bytes)
+                  (offset : Int32)
+                  (length : Int32)) : Unit
+          (kotlin-member-call write))
+        (class LimitedInputStream ((input : InputStream) (limitValue : Int))
+          (extends FilterInputStream input)
+          (val limit : Int limitValue)
+          (var count : Int (int 0))
+          (def (account (amount : Int32)) : Int32
+            (begin
+              (if (positiveCount amount)
+                (begin
+                  (set! count (+ count (int amount)))
+                  (if (inputCountExceeded count limit)
+                    (throw
+                      (illegalStateException
+                        (inputLimitExceededMessage limit))
+                      Unit)
+                    (begin)))
+                (begin))
+              amount))
+          (def (read-one) : Int32
+            (modifiers override)
+            (kotlin-name read)
+            (let ((value (superInputReadByte)))
+              (begin
+                (if (streamByteWasRead value)
+                  (begin
+                    (account (int32 1))
+                    (begin))
+                  (begin))
+                value)))
+          (def (read-buffer
+                 (buffer : Bytes)
+                 (offset : Int32)
+                 (length : Int32)) : Int32
+            (modifiers override)
+            (kotlin-name read)
+            (account
+              (superInputReadBuffer buffer offset length))))
+        (class LimitedOutputStream ((output : OutputStream) (limitValue : Int))
+          (extends FilterOutputStream output)
+          (val limit : Int limitValue)
+          (var count : Int (int 0))
+          (def (write-one (value : Int32)) : Unit
+            (modifiers override)
+            (kotlin-name write)
+            (begin
+              (if (outputSingleWriteExceeds count limit)
+                (throw
+                  (illegalStateException
+                    (outputLimitExceededMessage limit))
+                  Unit)
+                (begin))
+              (outputStreamWriteByte (filterOutputStreamOut this) value)
+              (set! count (+ count (int 1)))))
+          (def (write-buffer
+                 (buffer : Bytes)
+                 (offset : Int32)
+                 (length : Int32)) : Unit
+            (modifiers override)
+            (kotlin-name write)
+            (begin
+              (if (outputBufferWriteExceeds count (int length) limit)
+                (throw
+                  (illegalStateException
+                    (outputLimitExceededMessage limit))
+                  Unit)
+                (begin))
+              (outputStreamWriteBuffer
+                (filterOutputStreamOut this)
+                buffer
+                offset
+                length)
+              (set! count (+ count (int length))))))))
+
     (kotlin-file-lines "com/sfb/ssdreview/TruthStore.kt"
       (
        "package com.sfb.ssdreview"
@@ -12669,46 +12778,6 @@
 	       "        applyTruthJsonToSession(session, truthJsonObjectOrEmpty(truth))"
 	       "    }"
        ""
-       "    private class LimitedInputStream(input: InputStream, private val limit: Long) : FilterInputStream(input) {"
-       "        var count: Long = 0L"
-       "            private set"
-       ""
-       "        private fun account(amount: Int): Int {"
-       "            if (positiveCount(amount)) {"
-       "                count += amount.toLong()"
-       "                if (inputCountExceeded(count, limit)) throw IllegalStateException(inputLimitExceededMessage(limit))"
-       "            }"
-       "            return amount"
-       "        }"
-       ""
-       "        override fun read(): Int {"
-       "            val value = super.read()"
-       "            if (streamByteWasRead(value)) account(1)"
-       "            return value"
-       "        }"
-       "        override fun read(buffer: ByteArray, offset: Int, length: Int): Int ="
-       "            account(super.read(buffer, offset, length))"
-       "    }"
-       ""
-       "    private class LimitedOutputStream(output: OutputStream, private val limit: Long) : FilterOutputStream(output) {"
-       "        var count: Long = 0L"
-       "            private set"
-       ""
-       "        override fun write(value: Int) {"
-       "            if (outputSingleWriteExceeds(count, limit)) throw IllegalStateException(outputLimitExceededMessage(limit))"
-       "            out.write(value)"
-       "            count += 1L"
-       "        }"
-       ""
-       "        override fun write(buffer: ByteArray, offset: Int, length: Int) {"
-       "            if (outputBufferWriteExceeds(count, length.toLong(), limit)) {"
-       "                throw IllegalStateException(outputLimitExceededMessage(limit))"
-       "            }"
-       "            out.write(buffer, offset, length)"
-       "            count += length.toLong()"
-       "        }"
-       "    }"
-       ""
        "    private fun sha256Hex(bytes: ByteArray): String ="
        "        bytesToLowerHex(MessageDigest.getInstance(\"SHA-256\").digest(bytes))"
        ""