Skip to main content

vantage_table/
pagination.rs

1use vantage_expressions::traits::selectable::Selectable;
2
3/// Pagination configuration for tables
4#[derive(Debug, Clone, Copy, PartialEq, Eq)]
5pub struct Pagination {
6    page: i64,
7    items_per_page: i64,
8    /// Explicit skip for a random-access `[offset, offset+limit)` window. When
9    /// set, `skip()` returns it verbatim instead of deriving it from `page` —
10    /// so the offset need not be a multiple of the page size.
11    offset: Option<i64>,
12}
13
14impl Pagination {
15    /// Create new pagination with page number and items per page
16    pub fn new(page: i64, items_per_page: i64) -> Self {
17        Self {
18            page: page.max(1),
19            items_per_page: items_per_page.max(1),
20            offset: None,
21        }
22    }
23
24    /// Create pagination for an explicit `[offset, offset + limit)` window
25    /// (random access). Unlike [`new`](Self::new), the offset is independent of
26    /// the page size, so any absolute row range maps directly onto a query.
27    pub fn window(offset: i64, limit: i64) -> Self {
28        Self {
29            page: 1,
30            items_per_page: limit.max(1),
31            offset: Some(offset.max(0)),
32        }
33    }
34
35    /// Set the current page number (1-based)
36    pub fn set_page(&mut self, page: i64) {
37        self.page = page.max(1);
38    }
39
40    /// Set items per page
41    /// When changing page size, adjusts current page to keep focused item visible
42    pub fn set_ipp(&mut self, items_per_page: i64) {
43        let items_per_page = items_per_page.max(1);
44
45        let first_item_index = (self.page - 1) * self.items_per_page;
46        self.page = (first_item_index / items_per_page) + 1;
47        self.items_per_page = items_per_page;
48    }
49
50    /// Get the current page number (1-based)
51    pub fn get_page(&self) -> i64 {
52        self.page
53    }
54
55    /// Get items per page
56    pub fn get_ipp(&self) -> i64 {
57        self.items_per_page
58    }
59
60    /// Calculate limit value for queries
61    pub fn limit(&self) -> i64 {
62        self.items_per_page
63    }
64
65    /// Calculate skip/offset value for queries
66    pub fn skip(&self) -> i64 {
67        self.offset.unwrap_or((self.page - 1) * self.items_per_page)
68    }
69
70    /// Apply pagination to a select query
71    pub fn apply_on_select<S, E>(&self, select: &mut S)
72    where
73        S: Selectable<E>,
74    {
75        select.set_limit(Some(self.limit()), Some(self.skip()));
76    }
77}
78
79impl Default for Pagination {
80    fn default() -> Self {
81        Self {
82            page: 1,
83            items_per_page: 50,
84            offset: None,
85        }
86    }
87}