matrix_sdk/paginators/mod.rs
1// Copyright 2025 The Matrix.org Foundation C.I.C.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Stateful paginators to help with paginated APIs.
16
17mod room;
18pub mod thread;
19
20use matrix_sdk_base::deserialized_responses::TimelineEvent;
21pub use room::*;
22use ruma::OwnedEventId;
23
24/// Pagination token data, indicating in which state is the current pagination.
25#[derive(Clone, Debug, PartialEq)]
26pub enum PaginationToken {
27 /// We never had a pagination token, so we'll start back-paginating from the
28 /// end, or forward-paginating from the start.
29 None,
30 /// We paginated once before, and we received a prev/next batch token that
31 /// we may reuse for the next query.
32 HasMore(String),
33 /// We've hit one end of the timeline (either the start or the actual end),
34 /// so there's no need to continue paginating.
35 HitEnd,
36}
37
38impl From<Option<String>> for PaginationToken {
39 fn from(token: Option<String>) -> Self {
40 match token {
41 Some(val) => Self::HasMore(val),
42 None => Self::None,
43 }
44 }
45}
46
47/// The result of a single event pagination.
48#[derive(Debug)]
49pub struct PaginationResult {
50 /// Events returned during this pagination.
51 ///
52 /// If this is the result of a backward pagination, then the events are in
53 /// reverse topological order.
54 ///
55 /// If this is the result of a forward pagination, then the events are in
56 /// topological order.
57 pub events: Vec<TimelineEvent>,
58
59 /// Did we hit *an* end of the timeline?
60 ///
61 /// If this is the result of a backward pagination, this means we hit the
62 /// *start* of the timeline.
63 ///
64 /// If this is the result of a forward pagination, this means we hit the
65 /// *end* of the timeline.
66 pub hit_end_of_timeline: bool,
67}
68
69/// An error that happened when using a [`Paginator`].
70#[derive(Debug, thiserror::Error)]
71pub enum PaginatorError {
72 /// The target event could not be found.
73 #[error("target event with id {0} could not be found")]
74 EventNotFound(OwnedEventId),
75
76 /// We're trying to manipulate the paginator in the wrong state.
77 #[error("expected paginator state {expected:?}, observed {actual:?}")]
78 InvalidPreviousState {
79 /// The state we were expecting to see.
80 expected: PaginatorState,
81 /// The actual state when doing the check.
82 actual: PaginatorState,
83 },
84
85 /// There was another SDK error while paginating.
86 #[error("an error happened while paginating: {0}")]
87 SdkError(#[from] Box<crate::Error>),
88}