diff --git a/CHANGELOG.md b/CHANGELOG.md index fbf9abe81b5..8e530261905 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ ## 0.4.8 +* `Pagination` + * Add `PaginatedIterable` and `PaginatedIterator` + ## 0.4.7 * `Ktor` diff --git a/pagination/common/src/commonMain/kotlin/dev/inmo/micro_utils/pagination/utils/PaginatedIterable.kt b/pagination/common/src/commonMain/kotlin/dev/inmo/micro_utils/pagination/utils/PaginatedIterable.kt new file mode 100644 index 00000000000..035dabbae10 --- /dev/null +++ b/pagination/common/src/commonMain/kotlin/dev/inmo/micro_utils/pagination/utils/PaginatedIterable.kt @@ -0,0 +1,41 @@ +package dev.inmo.micro_utils.pagination.utils + +import dev.inmo.micro_utils.pagination.* + +class PaginatedIterator( + pageSize: Int, + private val countGetter: () -> Long, + private val paginationResultGetter: Pagination.() -> PaginationResult +) : Iterator { + private var pagination = FirstPagePagination(pageSize) + private val currentStack = mutableListOf() + override fun hasNext(): Boolean = currentStack.isNotEmpty() || (countGetter() < pagination.lastIndexExclusive) + + override fun next(): T { + if (currentStack.isEmpty()) { + val resultPagination = paginationResultGetter.invoke(pagination) + pagination = resultPagination.nextPage() + currentStack.addAll(resultPagination.results) + require(currentStack.isNotEmpty()) { "There is no elements left" } + } + return currentStack.removeFirst() + } +} + +class PaginatedIterable( + private val pageSize: Int, + private val countGetter: () -> Long, + private val paginationResultGetter: Pagination.() -> PaginationResult +) : Iterable { + override fun iterator(): Iterator = PaginatedIterator(pageSize, countGetter, paginationResultGetter) +} + +/** + * Will make iterable using incoming [countGetter] and [paginationResultGetter] + */ +@Suppress("NOTHING_TO_INLINE") +inline fun makeIterable( + noinline countGetter: () -> Long, + pageSize: Int = defaultMediumPageSize, + noinline paginationResultGetter: Pagination.() -> PaginationResult +): Iterable = PaginatedIterable(pageSize, countGetter, paginationResultGetter)