Move SSD PDF choice sorting to typed Kotlin

ober

d8a5f6d6458fc9747a3f398c2f0350ea56969f3b

diff --git a/.build.yml b/.build.yml
index b258c1d..70af0c0 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#7add929a45a7bbdfbd50dbea56b943bdcbb72e95"
+  - "https://git.sr.ht/~lisp/jerboa#bebe21de07a4914bf63d1419a29a18b739f65e86"
   # 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)" = 7add929a45a7bbdfbd50dbea56b943bdcbb72e95
-      test "$(git -C ../jerboa rev-parse 'HEAD^{tree}')" = fa69a6d72e022a099b2eca36884501beaa8155e2
+      test "$(git -C ../jerboa rev-parse HEAD)" = bebe21de07a4914bf63d1419a29a18b739f65e86
+      test "$(git -C ../jerboa rev-parse 'HEAD^{tree}')" = 56db688f33668ab6000749af03b58fea743939e7
       JERBOA="chez --libdirs .:../jerboa/lib --script" make test
diff --git a/dependencies.lock.json b/dependencies.lock.json
index 369516d..10911ec 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": "7add929a45a7bbdfbd50dbea56b943bdcbb72e95",
-    "tree": "fa69a6d72e022a099b2eca36884501beaa8155e2"
+    "commit": "bebe21de07a4914bf63d1419a29a18b739f65e86",
+    "tree": "56db688f33668ab6000749af03b58fea743939e7"
   },
   "assurance_tools": {
     "osv_scanner": {
diff --git a/scripts/verify-supply-chain.sh b/scripts/verify-supply-chain.sh
index 968fcd0..2f31226 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=7add929a45a7bbdfbd50dbea56b943bdcbb72e95 # gitsafe:ignore
-jerboa_tree=fa69a6d72e022a099b2eca36884501beaa8155e2 # gitsafe:ignore
+jerboa_commit=bebe21de07a4914bf63d1419a29a18b739f65e86 # gitsafe:ignore
+jerboa_tree=56db688f33668ab6000749af03b58fea743939e7 # 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 ea4e78e..6c2fe39 100644
--- a/templates/ssd-review.ss
+++ b/templates/ssd-review.ss
@@ -1182,7 +1182,8 @@
         (export make-SsdPdfChoice SsdPdfChoice?
                 SsdPdfChoice-label SsdPdfChoice-uri
                 ssdPdfChoiceLabels ssdPdfChoiceUriAt
-                ssdPdfUniqueChoicesByLabel ssdPdfFoundStatus)
+                ssdPdfUniqueChoicesByLabel ssdPdfFoundStatus
+                ssdPdfUniqueSortedLimitedChoices)
         (type Int32)
         (type Uri)
         (record SsdPdfChoice
@@ -1213,7 +1214,57 @@
                     (begin
                       (mutable-set-add! seen key)
                       (mutable-list-add! out choice)
-                      out)))))))))
+                      out)))))))
+        (def (ssdPdfChoiceBeforeByLabel? (candidate : SsdPdfChoice)
+                                         (existing : SsdPdfChoice)) : Bool
+          (< (string-compare-to
+               (string-lowercase (SsdPdfChoice-label candidate))
+               (string-lowercase (SsdPdfChoice-label existing)))
+             (int32 0)))
+        (def (ssdPdfSortedInsertIndex (sorted : (MutableList SsdPdfChoice))
+                                      (choice : SsdPdfChoice)) : Int32
+          (for/fold ((found (int32 -1)))
+                    ((i (in-range (int32 0) (list-size sorted))))
+            (if (>= found (int32 0))
+              found
+              (if (ssdPdfChoiceBeforeByLabel? choice (list-ref sorted i))
+                i
+                found))))
+        (def (ssdPdfInsertSorted (sorted : (MutableList SsdPdfChoice))
+                                 (choice : SsdPdfChoice)) : (MutableList SsdPdfChoice)
+          (let ((insertAt (ssdPdfSortedInsertIndex sorted choice)))
+            (if (< insertAt (int32 0))
+              (begin
+                (mutable-list-add! sorted choice)
+                sorted)
+              (let ((out (mutable-list-empty SsdPdfChoice)))
+                (begin
+                  (for/fold ((ignored (int32 0)))
+                            ((i (in-range (int32 0) (list-size sorted))))
+                    (begin
+                      (if (= i insertAt)
+                        (begin
+                          (mutable-list-add! out choice)
+                          (mutable-list-add! out (list-ref sorted i)))
+                        (mutable-list-add! out (list-ref sorted i)))
+                      ignored))
+                  out)))))
+        (def (ssdPdfChoicesSortedByLabel (choices : (MutableList SsdPdfChoice))) : (MutableList SsdPdfChoice)
+          (for/fold ((sorted (mutable-list-empty SsdPdfChoice)))
+                    ((i (in-range (int32 0) (list-size choices))))
+            (ssdPdfInsertSorted sorted (list-ref choices i))))
+        (def (ssdPdfTakeChoices (choices : (MutableList SsdPdfChoice)) (limit : Int32)) : (MutableList SsdPdfChoice)
+          (let ((end (if (< (list-size choices) limit) (list-size choices) limit)))
+            (for/fold ((out (mutable-list-empty SsdPdfChoice)))
+                      ((i (in-range (int32 0) end)))
+              (begin
+                (mutable-list-add! out (list-ref choices i))
+                out))))
+        (def (ssdPdfUniqueSortedLimitedChoices (choices : (List SsdPdfChoice))
+                                              (limit : Int32)) : (MutableList SsdPdfChoice)
+          (ssdPdfTakeChoices
+            (ssdPdfChoicesSortedByLabel (ssdPdfUniqueChoicesByLabel choices))
+            limit))))
 
     (typed-kotlin-file "com/sfb/ssdreview/TruthStoreRecords.kt"
       (kotlin-imports (java io File) (java net URL))
@@ -4992,7 +5043,7 @@
        "    }"
        ""
        "    private fun uniquePdfChoices(choices: List<SsdPdfChoice>): List<SsdPdfChoice> {"
-       "        return ssdPdfUniqueChoicesByLabel(choices).sortedBy { it.label.lowercase() }.take(MAX_SSD_PDF_CHOICES)"
+       "        return ssdPdfUniqueSortedLimitedChoices(choices, MAX_SSD_PDF_CHOICES)"
        "    }"
        ""
        "    private fun hasDirectDownloadAccess(): Boolean {"