Move SSD cursor guards to typed Kotlin

ober

ae06ca57e715b47c97562ea3be045233afaa865b

diff --git a/templates/ssd-review.ss b/templates/ssd-review.ss
index 370cf10..d5d8f98 100644
--- a/templates/ssd-review.ss
+++ b/templates/ssd-review.ss
@@ -4325,7 +4325,9 @@
     (typed-kotlin-file "com/sfb/ssdreview/UiTextHelpers.kt"
       (kotlin-imports (java io File)
                       (android content Intent)
+                      (android database Cursor)
                       (android net Uri)
+                      (android os ParcelFileDescriptor)
                       (androidx documentfile provider DocumentFile)
                       (org json JSONObject))
       (typed-library (com sfb ssdreview)
@@ -4387,6 +4389,7 @@
                 shouldPersistLoadedPdfState viewportScalePreferencePresent
                 viewportScalePreferenceMissing
                 lastPdfUriMismatch lastViewportPageMismatch
+                cursorPresent parcelFileDescriptorPresent
                 displayNameColumnPresent displayNameCursorHasFirstRow
                 currentLoadMatches currentLoadStale
                 packageUriText mediaStorePdfSelection
@@ -4420,8 +4423,10 @@
         (type Float32)
         (type Char)
         (type File)
+        (type Cursor)
         (type Intent)
         (type Uri)
+        (type ParcelFileDescriptor)
         (type DocumentFile)
         (type JSONObject)
         (type SsdSession)
@@ -4550,6 +4555,11 @@
                                        (maxDepth : Int32)) : Bool
           (or (> depth maxDepth)
               (>= currentChoices limit)))
+        (def (cursorPresent (cursor : (Nullable Cursor))) : Bool
+          (not (nullable-null? cursor)))
+        (def (parcelFileDescriptorPresent
+               (descriptor : (Nullable ParcelFileDescriptor))) : Bool
+          (not (nullable-null? descriptor)))
         (def (documentFilePresent (file : (Nullable DocumentFile))) : Bool
           (not (nullable-null? file)))
         (def (deleteDocumentFileIfPresent (file : (Nullable DocumentFile))) : Unit
@@ -7452,13 +7462,14 @@
        "        )"
        "        val selection = mediaStorePdfSelection(MediaStore.MediaColumns.MIME_TYPE, MediaStore.MediaColumns.DISPLAY_NAME)"
        "        val selectionArgs = arrayOf(\"application/pdf\", \"%.pdf\")"
-       "        contentResolver.query("
+       "        val downloadCursor = contentResolver.query("
        "            MediaStore.Downloads.EXTERNAL_CONTENT_URI,"
        "            projection,"
        "            selection,"
        "            selectionArgs,"
        "            mediaStoreDisplayNameSort(MediaStore.MediaColumns.DISPLAY_NAME)"
-       "        )?.use { cursor ->"
+       "        )"
+       "        if (cursorPresent(downloadCursor)) checkNotNull(downloadCursor).use { cursor ->"
        "            val idCol = cursor.getColumnIndexOrThrow(MediaStore.Downloads._ID)"
        "            val nameCol = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DISPLAY_NAME)"
        "            val pathCol = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.RELATIVE_PATH)"
@@ -7676,13 +7687,15 @@
        "    }"
        ""
        "    private fun openPdfRenderer(uri: Uri): PdfRenderer {"
-       "        val pfd: ParcelFileDescriptor = contentResolver.openFileDescriptor(uri, \"r\")"
-       "            ?: throw IllegalArgumentException(\"Unable to open PDF\")"
+       "        val descriptor = contentResolver.openFileDescriptor(uri, \"r\")"
+       "        if (!parcelFileDescriptorPresent(descriptor)) throw IllegalArgumentException(\"Unable to open PDF\")"
+       "        val pfd: ParcelFileDescriptor = checkNotNull(descriptor)"
        "        return PdfRenderer(pfd)"
        "    }"
        ""
        "    private fun displayName(uri: Uri): String {"
-       "        contentResolver.query(uri, null, null, null, null)?.use { cursor ->"
+       "        val nameCursor = contentResolver.query(uri, null, null, null, null)"
+       "        if (cursorPresent(nameCursor)) checkNotNull(nameCursor).use { cursor ->"
        "            val index = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)"
        "            if (displayNameColumnPresent(index)) {"
        "                if (displayNameCursorHasFirstRow(cursor.moveToFirst())) {"