Move SSD native detection JSON parsing to typed Kotlin
ober
bed2723d46a8818e9a885c90ed0cb66e283a31e3
--- 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#79546b9d6d7f3fa15555c3b4193c2080b1ad4aed" + - "https://git.sr.ht/~lisp/jerboa#5ddcc1f4398dad190a45719fb4e1d1e26479b000" # 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)" = 79546b9d6d7f3fa15555c3b4193c2080b1ad4aed - test "$(git -C ../jerboa rev-parse 'HEAD^{tree}')" = ff5aa378868436fe9ef1f906f52a27aa27b9502e + test "$(git -C ../jerboa rev-parse HEAD)" = 5ddcc1f4398dad190a45719fb4e1d1e26479b000 + test "$(git -C ../jerboa rev-parse 'HEAD^{tree}')" = ea37e94e6d22df8c5221f5af6999ff0dc866e905 JERBOA="chez --libdirs .:../jerboa/lib --script" make test --- a/dependencies.lock.json +++ b/dependencies.lock.json @@ -11,8 +11,8 @@ "generator_runtime": { "name": "jerboa", "repository": "https://git.sr.ht/~lisp/jerboa", - "commit": "79546b9d6d7f3fa15555c3b4193c2080b1ad4aed", - "tree": "ff5aa378868436fe9ef1f906f52a27aa27b9502e" + "commit": "5ddcc1f4398dad190a45719fb4e1d1e26479b000", + "tree": "ea37e94e6d22df8c5221f5af6999ff0dc866e905" }, "assurance_tools": { "osv_scanner": { --- 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=79546b9d6d7f3fa15555c3b4193c2080b1ad4aed # gitsafe:ignore -jerboa_tree=ff5aa378868436fe9ef1f906f52a27aa27b9502e # gitsafe:ignore +jerboa_commit=5ddcc1f4398dad190a45719fb4e1d1e26479b000 # gitsafe:ignore +jerboa_tree=ea37e94e6d22df8c5221f5af6999ff0dc866e905 # gitsafe:ignore gradle_sha=20f1b1176237254a6fc204d8434196fa11a4cfb387567519c61556e8710aed78 jdk_macos_sha=8fa1eff40bb637a33613b2ccb8b12c70dc3661cc22cf8e784943715769a05336 jdk_linux_sha=d8afc263758141a66e0e3aafc321e783f7016696f4eaea067d340a269037d331 --- a/templates/ssd-review.ss +++ b/templates/ssd-review.ss @@ -1753,6 +1753,91 @@ (float32 h) "android-contour"))))))))))))))) + (typed-kotlin-file "com/sfb/ssdreview/SsdVisionJson.kt" + (kotlin-imports (org json JSONArray) (org json JSONObject)) + (typed-library (com sfb ssdreview) + (export nativeDetectionCellsFromJson nativeDetectionGroupsFromJson) + (type JSONArray) + (type JSONObject) + (type Int32) + (type SsdCell) + (type SsdGroup) + (def (nullableJsonArrayOrEmpty (raw : (Nullable JSONArray))) : JSONArray + (if (nullable-null? raw) + (json-array-empty) + (nullable-get raw))) + (def (nativeDetectionCellId (index : Int32)) : String + (string-append "c" + (string-pad-start (int32->string (+ index (int32 1))) (int32 4) #\0))) + (def (nativeDetectionGroupId (index : Int32)) : String + (string-append "g" + (string-pad-start (int32->string (+ index (int32 1))) (int32 4) #\0))) + (def (nativeDetectionCellsFromJson (raw : (Nullable JSONArray))) : (MutableList SsdCell) + (let ((cells (mutable-list-empty SsdCell))) + (let ((items (nullableJsonArrayOrEmpty raw))) + (begin + (for/fold ((ignored (int32 0))) + ((index (in-range (int32 0) (json-array-length items)))) + (let ((entry (json-array-opt-json-object items index))) + (if (nullable-null? entry) + ignored + (let ((json (nullable-get entry))) + (begin + (mutable-list-add! cells + (make-SsdCell + (json-object-opt-string-default json "id" + (nativeDetectionCellId index)) + (json-object-opt-float32 json "x") + (json-object-opt-float32 json "y") + (json-object-opt-float32 json "w") + (json-object-opt-float32 json "h") + (json-object-opt-string-default json "detector" "rust-color"))) + ignored))))) + cells)))) + (def (nativeDetectionGroupsFromJson (raw : (Nullable JSONArray))) : (MutableList SsdGroup) + (let ((groups (mutable-list-empty SsdGroup))) + (let ((items (nullableJsonArrayOrEmpty raw))) + (begin + (for/fold ((ignored (int32 0))) + ((index (in-range (int32 0) (json-array-length items)))) + (let ((entry (json-array-opt-json-object items index))) + (if (nullable-null? entry) + ignored + (let ((json (nullable-get entry))) + (let ((bboxArray (nullableJsonArrayOrEmpty + (json-object-opt-json-array json "bbox")))) + (let ((idsArray (nullableJsonArrayOrEmpty + (json-object-opt-json-array json "cell_ids")))) + (let ((ids (mutable-list-empty String))) + (begin + (for/fold ((idsIgnored (int32 0))) + ((idIndex (in-range (int32 0) (json-array-length idsArray)))) + (let ((id (json-array-opt-string idsArray idIndex))) + (if (string-blank? id) + idsIgnored + (begin + (mutable-list-add! ids id) + idsIgnored)))) + (mutable-list-add! groups + (make-SsdGroup + (json-object-opt-string-default json "id" + (nativeDetectionGroupId index)) + (json-object-opt-string json "label") + (json-object-opt-string json "box_type_id") + (json-object-opt-string-default json "status" "candidate") + (json-object-opt-int32-default json "count" (list-size ids)) + (float-array + (json-array-opt-float32 bboxArray (int32 0) (float32 0.0)) + (json-array-opt-float32 bboxArray (int32 1) (float32 0.0)) + (json-array-opt-float32 bboxArray (int32 2) (float32 0.0)) + (json-array-opt-float32 bboxArray (int32 3) (float32 0.0))) + ids + (json-object-opt-string-default json "firing_arc" + (json-object-opt-string json "arc")) + (json-object-opt-string json "notes"))) + ignored)))))))) + groups)))))) + (typed-kotlin-file "com/sfb/ssdreview/UiTextHelpers.kt" (typed-library (com sfb ssdreview) (export normalizeFiringArc normalizeLabel shouldReplaceGuessLabel @@ -3967,7 +4052,6 @@ "package com.sfb.ssdreview" "" "import android.graphics.Bitmap" - "import org.json.JSONArray" "import org.json.JSONObject" "" "object SsdVisionBridge {" @@ -3998,9 +4082,9 @@ " loadError = IllegalStateException(root.optString(\"error\", \"native detector failed\"))" " return null" " }" - " val cells = parseCells(root.optJSONArray(\"cells\"))" + " val cells = nativeDetectionCellsFromJson(root.optJSONArray(\"cells\"))" " if (cells.isEmpty()) return null" - " val groups = parseGroups(root.optJSONArray(\"groups\"))" + " val groups = nativeDetectionGroupsFromJson(root.optJSONArray(\"groups\"))" " return NativeDetection(cells, groups)" " }" "" @@ -4012,51 +4096,6 @@ " return pixelsToRgba(pixels)" " }" "" - " private fun parseCells(raw: JSONArray?): MutableList<SsdCell> {" - " val cells = mutableListOf<SsdCell>()" - " if (raw == null) return cells" - " for (index in 0 until raw.length()) {" - " val json = raw.optJSONObject(index) ?: continue" - " val id = json.optString(\"id\", \"c%04d\".format(index + 1))" - " cells.add(SsdCell(" - " id = id," - " x = json.optDouble(\"x\", 0.0).toFloat()," - " y = json.optDouble(\"y\", 0.0).toFloat()," - " w = json.optDouble(\"w\", 0.0).toFloat()," - " h = json.optDouble(\"h\", 0.0).toFloat()," - " detector = json.optString(\"detector\", \"rust-color\")" - " ))" - " }" - " return cells" - " }" - "" - " private fun parseGroups(raw: JSONArray?): MutableList<SsdGroup> {" - " val groups = mutableListOf<SsdGroup>()" - " if (raw == null) return groups" - " for (index in 0 until raw.length()) {" - " val json = raw.optJSONObject(index) ?: continue" - " val bboxArray = json.optJSONArray(\"bbox\") ?: JSONArray()" - " val idsArray = json.optJSONArray(\"cell_ids\") ?: JSONArray()" - " val ids = mutableListOf<String>()" - " for (idIndex in 0 until idsArray.length()) {" - " val id = idsArray.optString(idIndex)" - " if (id.isNotBlank()) ids.add(id)" - " }" - " groups.add(SsdGroup(" - " id = json.optString(\"id\", \"g%04d\".format(index + 1))," - " label = json.optString(\"label\")," - " boxTypeId = json.optString(\"box_type_id\")," - " status = json.optString(\"status\", \"candidate\")," - " count = json.optInt(\"count\", ids.size)," - " bbox = FloatArray(4) { bboxArray.optDouble(it, 0.0).toFloat() }," - " cellIds = ids," - " firingArc = json.optString(\"firing_arc\", json.optString(\"arc\"))," - " notes = json.optString(\"notes\")" - " ))" - " }" - " return groups" - " }" - "" " private external fun nativeDetectRgbaJson(width: Int, height: Int, rgba: ByteArray): String" "}" ))