Skip to main content

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 std::sync::Arc;
21
22use matrix_sdk_base::deserialized_responses::TimelineEvent;
23pub use room::*;
24use ruma::OwnedEventId;
25
26/// Pagination token data, indicating in which state is the current pagination.
27#[derive(Clone, Debug, PartialEq)]
28pub enum PaginationToken {
29    /// We never had a pagination token, so we'll start back-paginating from the
30    /// end, or forward-paginating from the start.
31    None,
32    /// We paginated once before, and we received a prev/next batch token that
33    /// we may reuse for the next query.
34    HasMore(String),
35    /// We've hit one end of the timeline (either the start or the actual end),
36    /// so there's no need to continue paginating.
37    HitEnd,
38}
39
40impl PaginationToken {
41    /// Convert to the token string, if we have one.
42    pub fn into_token(self) -> Option<String> {
43        match self {
44            Self::HasMore(token) => Some(token),
45            Self::None | Self::HitEnd => None,
46        }
47    }
48}
49
50impl From<Option<String>> for PaginationToken {
51    fn from(token: Option<String>) -> Self {
52        match token {
53            Some(val) => Self::HasMore(val),
54            None => Self::None,
55        }
56    }
57}
58
59/// The result of a single event pagination.
60#[derive(Debug)]
61pub struct PaginationResult {
62    /// Events returned during this pagination.
63    ///
64    /// If this is the result of a backward pagination, then the events are in
65    /// reverse topological order.
66    ///
67    /// If this is the result of a forward pagination, then the events are in
68    /// topological order.
69    pub events: Vec<TimelineEvent>,
70
71    /// Did we hit *an* end of the timeline?
72    ///
73    /// If this is the result of a backward pagination, this means we hit the
74    /// *start* of the timeline.
75    ///
76    /// If this is the result of a forward pagination, this means we hit the
77    /// *end* of the timeline.
78    pub hit_end_of_timeline: bool,
79}
80
81/// An error that happened when using a [`Paginator`].
82#[derive(Clone, Debug, thiserror::Error)]
83pub enum PaginatorError {
84    /// The target event could not be found.
85    #[error("target event with id {0} could not be found")]
86    EventNotFound(OwnedEventId),
87
88    /// We're trying to manipulate the paginator in the wrong state.
89    #[error("expected paginator state {expected:?}, observed {actual:?}")]
90    InvalidPreviousState {
91        /// The state we were expecting to see.
92        expected: PaginatorState,
93        /// The actual state when doing the check.
94        actual: PaginatorState,
95    },
96
97    /// There was another SDK error while paginating.
98    #[error("an error happened while paginating: {0}")]
99    SdkError(#[from] Arc<crate::Error>),
100}