1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.intentresolver.util.cursor
18 
19 import android.database.Cursor
20 import android.database.CursorWrapper
21 
22 /** Returns a Cursor that is truncated to contain only [count] elements. */
limitnull23 fun Cursor.limit(count: Int): Cursor =
24     object : CursorWrapper(this) {
25         override fun getCount(): Int = minOf(count, super.getCount())
26 
27         override fun getPosition(): Int = super.getPosition().coerceAtMost(count)
28 
29         override fun moveToLast(): Boolean = super.moveToPosition(getCount() - 1)
30 
31         override fun isFirst(): Boolean = getCount() != 0 && super.isFirst()
32 
33         override fun isLast(): Boolean = getCount() != 0 && super.getPosition() == getCount() - 1
34 
35         override fun isAfterLast(): Boolean = getCount() == 0 || super.getPosition() >= getCount()
36 
37         override fun isBeforeFirst(): Boolean = getCount() == 0 || super.isBeforeFirst()
38 
39         override fun moveToNext(): Boolean = super.moveToNext() && position < getCount()
40 
41         override fun moveToPosition(position: Int): Boolean =
42             super.moveToPosition(position) && position < getCount()
43     }
44 
45 /** Returns a Cursor that begins (index 0) at [newStartIndex] of the given Cursor. */
Cursornull46 fun Cursor.startAt(newStartIndex: Int): Cursor =
47     object : CursorWrapper(this) {
48         override fun getCount(): Int = (super.getCount() - newStartIndex).coerceAtLeast(0)
49 
50         override fun getPosition(): Int = (super.getPosition() - newStartIndex).coerceAtLeast(-1)
51 
52         override fun moveToFirst(): Boolean = super.moveToPosition(newStartIndex)
53 
54         override fun moveToNext(): Boolean = super.moveToNext() && position < count
55 
56         override fun moveToPrevious(): Boolean = super.moveToPrevious() && position >= 0
57 
58         override fun moveToPosition(position: Int): Boolean =
59             super.moveToPosition(position + newStartIndex) && position >= 0
60 
61         override fun isFirst(): Boolean = count != 0 && super.getPosition() == newStartIndex
62 
63         override fun isLast(): Boolean = count != 0 && super.isLast()
64 
65         override fun isBeforeFirst(): Boolean = count == 0 || super.getPosition() < newStartIndex
66 
67         override fun isAfterLast(): Boolean = count == 0 || super.isAfterLast()
68     }
69 
70 /** Returns a read-only non-movable view into the given Cursor. */
immobilizednull71 fun Cursor.immobilized(): Cursor =
72     object : CursorWrapper(this) {
73         private val unsupported: Nothing
74             get() = error("unsupported")
75 
76         override fun moveToFirst(): Boolean = unsupported
77 
78         override fun moveToLast(): Boolean = unsupported
79 
80         override fun move(offset: Int): Boolean = unsupported
81 
82         override fun moveToPosition(position: Int): Boolean = unsupported
83 
84         override fun moveToNext(): Boolean = unsupported
85 
86         override fun moveToPrevious(): Boolean = unsupported
87     }
88