Skip to content

Commit 31c8442

Browse files
committed
Fix anchor offset support
Two bugs: 1. Returned position is incorrect (always 0, in my tests) 2. Negative anchor offsets are off by one
1 parent 603cef2 commit 31c8442

1 file changed

Lines changed: 30 additions & 16 deletions

File tree

crates/jmap/src/api/query.rs

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use jmap_proto::{
99
object::JmapObject,
1010
types::state::State,
1111
};
12+
use std::cmp::{max, min};
1213
use types::id::Id;
1314

1415
pub 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

Comments
 (0)