@@ -9,6 +9,7 @@ use jmap_proto::{
99 object:: JmapObject ,
1010 types:: state:: State ,
1111} ;
12+ use std:: cmp:: { max, min} ;
1213use types:: id:: Id ;
1314
1415pub struct QueryResponseBuilder {
@@ -84,6 +85,7 @@ impl QueryResponseBuilder {
8485
8586 // Pagination
8687 if !self . has_anchor {
88+ // by position
8789 if self . position >= 0 {
8890 if self . position > 0 {
8991 self . position -= 1 ;
@@ -96,29 +98,41 @@ impl QueryResponseBuilder {
9698 } else {
9799 self . response . ids . push ( id) ;
98100 }
99- } else if self . anchor_offset >= 0 {
100- if !self . anchor_found {
101- if document_id != self . anchor {
102- return true ;
103- }
101+ } else {
102+ if document_id == self . anchor {
104103 self . anchor_found = true ;
104+ } else if !self . anchor_found {
105+ self . position += 1 ;
105106 }
106107
107- if self . anchor_offset > 0 {
108- self . anchor_offset -= 1 ;
109- } else {
108+ if self . anchor_found && self . anchor_offset == 0 {
109+ // once we're in a stable state (anchor found and offset zero), we'll keep pushing ids until we reach the limit
110110 self . response . ids . push ( id) ;
111111 if self . response . ids . len ( ) == self . limit {
112112 return false ;
113113 }
114- }
115- } else {
116- self . anchor_found = document_id == self . anchor ;
117- self . response . ids . push ( id) ;
118-
119- if self . anchor_found {
120- self . position = self . anchor_offset ;
121- return false ;
114+ } else if self . anchor_offset < 0 {
115+ // if the offset is negative, we need to "remember" the last -offset items we've seen
116+ self . response . ids . push ( id) ;
117+ if self . anchor_found {
118+ // once we find the anchor, trim the list to keep those we need to include in the returned list
119+ self . position += self . anchor_offset ;
120+ self . anchor_offset = 0 ;
121+ if self . response . ids . len ( ) > self . limit {
122+ self . response . ids = self . response . ids [ 0 ..self . limit ] . to_vec ( ) ;
123+ return false ;
124+ }
125+ if self . response . ids . len ( ) == self . limit {
126+ return false ;
127+ }
128+ } else if self . response . ids . len ( ) > self . anchor_offset . unsigned_abs ( ) as usize {
129+ // limit remembered items to -offset length
130+ self . response . ids . remove ( 0 ) ;
131+ }
132+ } else if self . anchor_found && self . anchor_offset > 0 {
133+ // if the offset is positive, we don't start pushing ids until we've skipped offset items after finding the anchor
134+ self . anchor_offset -= 1 ;
135+ self . position += 1 ;
122136 }
123137 }
124138
0 commit comments