Skip to content

Commit 1cb07fd

Browse files
committed
Negative LimitStage and OffsetStage evaluation
1 parent 22f33d7 commit 1cb07fd

File tree

1 file changed

+36
-3
lines changed
  • firebase-firestore/src/main/java/com/google/firebase/firestore/pipeline

1 file changed

+36
-3
lines changed

firebase-firestore/src/main/java/com/google/firebase/firestore/pipeline/stage.kt

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,13 @@ import com.google.firebase.firestore.util.Preconditions
2929
import com.google.firestore.v1.Pipeline
3030
import com.google.firestore.v1.Value
3131
import kotlinx.coroutines.flow.Flow
32+
import kotlinx.coroutines.flow.drop
33+
import kotlinx.coroutines.flow.emptyFlow
3234
import kotlinx.coroutines.flow.filter
3335
import kotlinx.coroutines.flow.flow
34-
import kotlinx.coroutines.flow.flowOf
36+
import kotlinx.coroutines.flow.forEach
3537
import kotlinx.coroutines.flow.map
38+
import kotlinx.coroutines.flow.skip
3639
import kotlinx.coroutines.flow.take
3740
import kotlinx.coroutines.flow.toList
3841

@@ -533,8 +536,21 @@ internal constructor(private val limit: Int, options: InternalOptions = Internal
533536
override fun evaluate(
534537
context: EvaluationContext,
535538
inputs: Flow<MutableDocument>
536-
): Flow<MutableDocument> = if (limit > 0) inputs.take(limit) else flowOf()
537-
539+
): Flow<MutableDocument> =
540+
when {
541+
limit > 0 -> inputs.take(limit)
542+
limit < 0 ->
543+
flow {
544+
val limitLast = -limit
545+
val buffer = ArrayDeque<MutableDocument>(limitLast)
546+
inputs.collect { doc ->
547+
if (buffer.size == limitLast) buffer.removeFirst()
548+
buffer.add(doc)
549+
}
550+
buffer.forEach { emit(it) }
551+
}
552+
else -> emptyFlow()
553+
}
538554
override fun args(userDataReader: UserDataReader): Sequence<Value> =
539555
sequenceOf(encodeValue(limit))
540556
}
@@ -545,6 +561,23 @@ internal constructor(private val offset: Int, options: InternalOptions = Interna
545561
override fun self(options: InternalOptions) = OffsetStage(offset, options)
546562
override fun args(userDataReader: UserDataReader): Sequence<Value> =
547563
sequenceOf(encodeValue(offset))
564+
override fun evaluate(
565+
context: EvaluationContext,
566+
inputs: Flow<MutableDocument>
567+
): Flow<MutableDocument> =
568+
when {
569+
offset > 0 -> inputs.drop(offset)
570+
offset < 0 ->
571+
flow {
572+
val offsetLast = -offset
573+
val buffer = ArrayDeque<MutableDocument>(offsetLast)
574+
inputs.collect { doc ->
575+
if (buffer.size == offsetLast) emit(buffer.removeFirst())
576+
buffer.add(doc)
577+
}
578+
}
579+
else -> inputs
580+
}
548581
}
549582

550583
internal class SelectStage

0 commit comments

Comments
 (0)