Generate SSD box type loading from typed Jerboa

ober

e0b9534d22d7bed0eade8e4dc4d8d68ed5548370

diff --git a/.build.yml b/.build.yml
index efc4a06..b67de89 100644
--- a/.build.yml
+++ b/.build.yml
@@ -5,7 +5,7 @@ packages:
   - make=4.4.1-r4
 sources:
   # Build dependency: full immutable commit, mirrored in dependencies.lock.json.
-  - "https://git.sr.ht/~lisp/jerboa#fc3264c8101a7892d13b11b8c223946df95adaf5"
+  - "https://git.sr.ht/~lisp/jerboa#4128d613222aa16f9d2cb8b7c311c73fb4760ecf"
   # The second source is the build subject selected by the SourceHut submitter.
   - https://git.sr.ht/~lisp/jerboa-android
 tasks:
@@ -14,6 +14,6 @@ tasks:
       test "$(apk info -v chez-scheme)" = chez-scheme-10.3.0-r2
       test "$(apk info -v git)" = git-2.54.0-r0
       test "$(apk info -v make)" = make-4.4.1-r4
-      test "$(git -C ../jerboa rev-parse HEAD)" = fc3264c8101a7892d13b11b8c223946df95adaf5
-      test "$(git -C ../jerboa rev-parse 'HEAD^{tree}')" = 43991ea0c37ca239fb5742ecf88616295481f5e3
+      test "$(git -C ../jerboa rev-parse HEAD)" = 4128d613222aa16f9d2cb8b7c311c73fb4760ecf
+      test "$(git -C ../jerboa rev-parse 'HEAD^{tree}')" = 0100bf29761be1324a8e3f811c03702a9c609fb8
       JERBOA="chez --libdirs .:../jerboa/lib --script" make test
diff --git a/dependencies.lock.json b/dependencies.lock.json
index e32fee9..18a7884 100644
--- a/dependencies.lock.json
+++ b/dependencies.lock.json
@@ -11,8 +11,8 @@
   "generator_runtime": {
     "name": "jerboa",
     "repository": "https://git.sr.ht/~lisp/jerboa",
-    "commit": "fc3264c8101a7892d13b11b8c223946df95adaf5",
-    "tree": "43991ea0c37ca239fb5742ecf88616295481f5e3"
+    "commit": "4128d613222aa16f9d2cb8b7c311c73fb4760ecf",
+    "tree": "0100bf29761be1324a8e3f811c03702a9c609fb8"
   },
   "assurance_tools": {
     "osv_scanner": {
diff --git a/scripts/verify-supply-chain.sh b/scripts/verify-supply-chain.sh
index 56e6c4d..36003a5 100755
--- a/scripts/verify-supply-chain.sh
+++ b/scripts/verify-supply-chain.sh
@@ -3,8 +3,8 @@ set -eu
 
 repo=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd -P)
 lock="$repo/dependencies.lock.json"
-jerboa_commit=fc3264c8101a7892d13b11b8c223946df95adaf5 # gitsafe:ignore
-jerboa_tree=43991ea0c37ca239fb5742ecf88616295481f5e3 # gitsafe:ignore
+jerboa_commit=4128d613222aa16f9d2cb8b7c311c73fb4760ecf # gitsafe:ignore
+jerboa_tree=0100bf29761be1324a8e3f811c03702a9c609fb8 # gitsafe:ignore
 gradle_sha=20f1b1176237254a6fc204d8434196fa11a4cfb387567519c61556e8710aed78
 jdk_macos_sha=8fa1eff40bb637a33613b2ccb8b12c70dc3661cc22cf8e784943715769a05336
 jdk_linux_sha=d8afc263758141a66e0e3aafc321e783f7016696f4eaea067d340a269037d331
diff --git a/templates/ssd-review.ss b/templates/ssd-review.ss
index 9d7180b..5857391 100644
--- a/templates/ssd-review.ss
+++ b/templates/ssd-review.ss
@@ -122,45 +122,6 @@
                           (findPartialBoxTypes items lowered normalized))
                         exact))))))))
 
-    (typed-kotlin-file "com/sfb/ssdreview/BoxTypeAndroid.kt"
-      (kotlin-imports (android content Context))
-      (typed-library (com sfb ssdreview)
-        (export boxTypeRawIsWeapon resolvedBoxTypeNameOr resolvedBoxTypeIdOr
-                boxTypesLoadAndroid boxTypesResolveAndroid boxTypesDisplayAndroid)
-        (type Context)
-        (extern (boxTypesResolve (context : Context) (raw : String)) : (Nullable BoxType)
-          (kotlin-call BoxTypes resolve))
-        (extern (boxTypesLoadRaw (context : Context)) : (List BoxType)
-          (kotlin-call BoxTypes load))
-        (extern (boxTypesDisplayRaw (context : Context) (id : String)) : String
-          (kotlin-call BoxTypes display))
-        (def (boxTypesLoadAndroid (context : Context)) : (List BoxType)
-          (boxTypesLoadRaw context))
-        (def (boxTypesResolveAndroid
-               (context : Context)
-               (raw : String)) : (Nullable BoxType)
-          (boxTypesResolve context raw))
-        (def (boxTypesDisplayAndroid
-               (context : Context)
-               (id : String)) : String
-          (boxTypesDisplayRaw context id))
-        (def (resolvedBoxTypeNameOr (boxType : (Nullable BoxType)) (fallback : String)) : String
-          (if (nullable-null? boxType)
-              fallback
-              (BoxType-name (nullable-get boxType))))
-        (def (resolvedBoxTypeIdOr (boxType : (Nullable BoxType)) (fallback : String)) : String
-          (if (nullable-null? boxType)
-              fallback
-              (BoxType-id (nullable-get boxType))))
-        (def (boxTypeRawIsWeapon (context : Context) (raw : String)) : Bool
-          (let ((text (string-trim raw)))
-            (if (string-blank? text)
-                #f
-                (boxTypeIsWeapon
-                  (resolvedBoxTypeNameOr
-                    (boxTypesResolve context text)
-                       text)))))))
-
     (typed-kotlin-file "com/sfb/ssdreview/BoxTypeCsv.kt"
       (typed-library (com sfb ssdreview)
         (export parseBoxTypeCsvLine boxTypesFromCsvText)
@@ -3306,7 +3267,7 @@
         (type Float32)
         (type FloatArray)
         (extern (boxTypesResolve (context : Context) (raw : String)) : (Nullable BoxType)
-          (kotlin-call BoxTypes resolve))
+          (kotlin-call boxTypesResolveAndroid))
         (extern (nearbyTextForOcr (words : (MutableList OcrWord))
                                   (bbox : FloatArray)
                                   (imageWidth : Int32)
@@ -9014,7 +8975,7 @@
                 shouldKeepLabelForBoxTypeAndroid)
         (type Context)
         (extern (boxTypesResolve (context : Context) (raw : String)) : (Nullable BoxType)
-          (kotlin-call BoxTypes resolve))
+          (kotlin-call boxTypesResolveAndroid))
         (def (nullableBoxTypeName (boxType : (Nullable BoxType))) : (Nullable String)
           (if (nullable-null? boxType)
               (nullable-none String)
@@ -9062,7 +9023,7 @@
         (type Context)
         (type Int32)
         (extern (boxTypesResolve (context : Context) (raw : String)) : (Nullable BoxType)
-          (kotlin-call BoxTypes resolve))
+          (kotlin-call boxTypesResolveAndroid))
         (def (nullableBoxTypeId (boxType : (Nullable BoxType))) : (Nullable String)
           (if (nullable-null? boxType)
               (nullable-none String)
@@ -9724,6 +9685,57 @@
                         (begin)))
                     (outputStreamWrite output buffer (int32 0) read)))))))))
 
+    (typed-kotlin-file "com/sfb/ssdreview/BoxTypeAndroid.kt"
+      (kotlin-imports (android content Context)
+                      (android content res AssetManager)
+                      (java io InputStream))
+      (typed-library (com sfb ssdreview)
+        (export boxTypeRawIsWeapon resolvedBoxTypeNameOr resolvedBoxTypeIdOr
+                boxTypesLoadAndroid boxTypesResolveAndroid boxTypesDisplayAndroid)
+        (type Context)
+        (type AssetManager)
+        (type InputStream)
+        (extern (contextAssets (context : Context)) : AssetManager
+          (kotlin-member-get assets))
+        (extern (assetManagerOpen
+                  (assets : AssetManager)
+                  (name : String)) : InputStream
+          (kotlin-member-call open))
+        (extern (boxTypeInputStreamClose (input : InputStream)) : Unit
+          (kotlin-member-call close))
+        (def (boxTypesCsvText (context : Context)) : String
+          (let ((input (assetManagerOpen (contextAssets context) "box_types.csv")))
+            (let ((text (utf8->string (readBoundedBytes input (int 262144)))))
+              (begin
+                (boxTypeInputStreamClose input)
+                text))))
+        (def (boxTypesLoadAndroid (context : Context)) : (List BoxType)
+          (boxTypesFromCsvText (boxTypesCsvText context)))
+        (def (boxTypesResolveAndroid
+               (context : Context)
+               (raw : String)) : (Nullable BoxType)
+          (resolveBoxType (boxTypesLoadAndroid context) raw))
+        (def (boxTypesDisplayAndroid
+               (context : Context)
+               (id : String)) : String
+          (boxTypeDisplayById (boxTypesLoadAndroid context) id))
+        (def (resolvedBoxTypeNameOr (boxType : (Nullable BoxType)) (fallback : String)) : String
+          (if (nullable-null? boxType)
+              fallback
+              (BoxType-name (nullable-get boxType))))
+        (def (resolvedBoxTypeIdOr (boxType : (Nullable BoxType)) (fallback : String)) : String
+          (if (nullable-null? boxType)
+              fallback
+              (BoxType-id (nullable-get boxType))))
+        (def (boxTypeRawIsWeapon (context : Context) (raw : String)) : Bool
+          (let ((text (string-trim raw)))
+            (if (string-blank? text)
+                #f
+                (boxTypeIsWeapon
+                  (resolvedBoxTypeNameOr
+                    (boxTypesResolveAndroid context text)
+                       text)))))))
+
     (typed-kotlin-file "com/sfb/ssdreview/RemoteTruthQuery.kt"
       (typed-library (com sfb ssdreview)
         (export remoteTruthQuery)
@@ -9744,34 +9756,6 @@
                         "&dpi="
                         (int32->string (SsdSession-dpi session))))))))))))
 
-    (kotlin-file-lines "com/sfb/ssdreview/BoxTypes.kt"
-      (
-       "package com.sfb.ssdreview"
-       ""
-       "import android.content.Context"
-       ""
-       "object BoxTypes {"
-       "    private var cacheLoaded = false"
-       "    private var cache: MutableList<BoxType> = mutableListOf()"
-       ""
-       "    fun load(context: Context): List<BoxType> {"
-       "        if (cacheLoaded) return cache"
-       "        val items = boxTypesFromCsvText(context.assets.open(\"box_types.csv\").bufferedReader().use { it.readText() })"
-       "        cache = items"
-       "        cacheLoaded = true"
-       "        return items"
-       "    }"
-       ""
-       "    fun resolve(context: Context, raw: String): BoxType? {"
-       "        return resolveBoxType(load(context), raw)"
-       "    }"
-       ""
-       "    fun display(context: Context, id: String): String {"
-       "        return boxTypeDisplayById(load(context), id)"
-       "    }"
-       ""
-       "}"
-       ))
     (kotlin-file-lines "com/sfb/ssdreview/MainActivity.kt"
       (
        "package com.sfb.ssdreview"