Move SSD truth image dimensions to typed Kotlin

ober

03d96582008b089f81f343ae1e9199fba4f03fba

diff --git a/.build.yml b/.build.yml
index b2667ad..89e54bf 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#5ddcc1f4398dad190a45719fb4e1d1e26479b000"
+  - "https://git.sr.ht/~lisp/jerboa#52f5326a4d8ff0b34274a6b7c6260a8bc5fe1329"
   # 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)" = 5ddcc1f4398dad190a45719fb4e1d1e26479b000
-      test "$(git -C ../jerboa rev-parse 'HEAD^{tree}')" = ea37e94e6d22df8c5221f5af6999ff0dc866e905
+      test "$(git -C ../jerboa rev-parse HEAD)" = 52f5326a4d8ff0b34274a6b7c6260a8bc5fe1329
+      test "$(git -C ../jerboa rev-parse 'HEAD^{tree}')" = 24fc6d28102255170cd37dd3c8dcbd5e415ac4a6
       JERBOA="chez --libdirs .:../jerboa/lib --script" make test
diff --git a/dependencies.lock.json b/dependencies.lock.json
index bc97af4..aeb5668 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": "5ddcc1f4398dad190a45719fb4e1d1e26479b000",
-    "tree": "ea37e94e6d22df8c5221f5af6999ff0dc866e905"
+    "commit": "52f5326a4d8ff0b34274a6b7c6260a8bc5fe1329",
+    "tree": "24fc6d28102255170cd37dd3c8dcbd5e415ac4a6"
   },
   "assurance_tools": {
     "osv_scanner": {
diff --git a/scripts/verify-supply-chain.sh b/scripts/verify-supply-chain.sh
index a5a0652..e9146f8 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=5ddcc1f4398dad190a45719fb4e1d1e26479b000 # gitsafe:ignore
-jerboa_tree=ea37e94e6d22df8c5221f5af6999ff0dc866e905 # gitsafe:ignore
+jerboa_commit=52f5326a4d8ff0b34274a6b7c6260a8bc5fe1329 # gitsafe:ignore
+jerboa_tree=24fc6d28102255170cd37dd3c8dcbd5e415ac4a6 # 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 b9e4de0..3420add 100644
--- a/templates/ssd-review.ss
+++ b/templates/ssd-review.ss
@@ -1028,7 +1028,7 @@
     (typed-kotlin-file "com/sfb/ssdreview/TruthJson.kt"
       (kotlin-imports (org json JSONArray) (org json JSONObject))
       (typed-library (com sfb ssdreview)
-        (export truthGroupCount)
+        (export truthGroupCount imageWidth imageHeight)
         (type JSONArray)
         (type JSONObject)
         (type Int32)
@@ -1036,10 +1036,30 @@
           (if (nullable-null? raw)
               (json-array-empty)
               (nullable-get raw)))
+        (def (truthJsonObjectOrEmpty (raw : (Nullable JSONObject))) : JSONObject
+          (if (nullable-null? raw)
+              (json-object-empty)
+              (nullable-get raw)))
+        (def (positiveOrOne (value : Int32)) : Int32
+          (if (< value (int32 1))
+              (int32 1)
+              value))
         (def (truthGroupCount (truth : JSONObject)) : Int32
           (json-array-length
             (truthJsonArrayOrEmpty
-              (json-object-opt-json-array truth "groups"))))))
+              (json-object-opt-json-array truth "groups"))))
+        (def (imageWidth (truth : JSONObject)) : Int32
+          (positiveOrOne
+            (json-object-opt-int32-default
+              (truthJsonObjectOrEmpty (json-object-opt-json-object truth "image"))
+              "width"
+              (int32 1))))
+        (def (imageHeight (truth : JSONObject)) : Int32
+          (positiveOrOne
+            (json-object-opt-int32-default
+              (truthJsonObjectOrEmpty (json-object-opt-json-object truth "image"))
+              "height"
+              (int32 1))))))
 
     (typed-kotlin-file "com/sfb/ssdreview/Guess.kt"
       (typed-library (com sfb ssdreview)
@@ -5799,12 +5819,6 @@
        "        return file.inputStream().use { readBoundedBytes(it, MAX_ZIP_ENTRY_BYTES).decodeToString() }"
        "    }"
        ""
-       "    private fun imageWidth(truth: JSONObject): Int ="
-       "        truth.optJSONObject(\"image\")?.optInt(\"width\", 1)?.coerceAtLeast(1) ?: 1"
-       ""
-       "    private fun imageHeight(truth: JSONObject): Int ="
-       "        truth.optJSONObject(\"image\")?.optInt(\"height\", 1)?.coerceAtLeast(1) ?: 1"
-       ""
        "    private fun groupFeatures(group: JSONObject, imageWidth: Int, imageHeight: Int): JSONObject {"
        "        val bbox = group.optJSONArray(\"bbox\") ?: JSONArray()"
        "        val x1 = bbox.optDouble(0, 0.0)"