rdb_pagination_core/
pagination.rs

1/// Struct representing pagination information.
2///
3/// # Examples
4///
5/// ```rust
6/// # use rdb_pagination_core::Pagination;
7/// #
8/// let pagination =
9///     Pagination::new().items_per_page(20).total_items(50).page(1);
10///
11/// let total_pages = pagination.get_total_pages(); // 3
12/// ```
13#[derive(Debug, Clone)]
14#[cfg_attr(feature = "serde", derive(serde::Serialize))]
15pub struct Pagination {
16    page:           usize,
17    total_pages:    usize,
18    items_per_page: usize,
19    total_items:    usize,
20}
21
22impl Pagination {
23    #[allow(clippy::new_without_default)]
24    /// Create a new `Pagination`.
25    ///
26    /// ```rust
27    /// # use rdb_pagination_core::Pagination;
28    /// #
29    /// let pagination = Pagination::new();
30    /// // equals to
31    /// // let pagination = Pagination {
32    /// //     page:           1,
33    /// //     total_pages:    1,
34    /// //     items_per_page: 0,
35    /// //     total_items:    0,
36    /// // };
37    /// ```
38    #[inline]
39    pub const fn new() -> Self {
40        Self {
41            page: 1, total_pages: 1, items_per_page: 0, total_items: 0
42        }
43    }
44
45    /// Set the page number.
46    ///
47    /// * If the value is `0`, it will be changed to `1`.
48    /// * If the value is bigger than `total_pages`, it will be changed to `total_pages`.
49    #[inline]
50    pub const fn page(mut self, page: usize) -> Self {
51        if page == 0 {
52            self.page = 1;
53        } else if page > self.total_pages {
54            self.page = self.total_pages;
55        } else {
56            self.page = page;
57        }
58
59        self
60    }
61
62    /// Number of items per page.
63    ///
64    /// * If the value is `0`, it means **all items in a single page**.
65    #[inline]
66    pub const fn items_per_page(mut self, items_per_page: usize) -> Self {
67        self.items_per_page = items_per_page;
68
69        self.update_total_pages()
70    }
71
72    /// Total number of items.
73    #[inline]
74    pub const fn total_items(mut self, total_items: usize) -> Self {
75        self.total_items = total_items;
76
77        self.update_total_pages()
78    }
79
80    #[inline]
81    const fn update_total_pages(mut self) -> Self {
82        match self.items_per_page {
83            0 => {
84                self.total_pages = 1;
85            },
86            1 => self.total_pages = self.total_items,
87            _ => {
88                self.total_pages =
89                    (self.total_items + (self.items_per_page - 1)) / self.items_per_page
90            },
91        }
92
93        if self.page < self.total_pages {
94            self.page = self.total_pages;
95        }
96
97        self
98    }
99}
100
101impl Pagination {
102    /// Get the page number.
103    #[inline]
104    pub const fn get_page(&self) -> usize {
105        self.page
106    }
107
108    /// Get the total number of pages.
109    #[inline]
110    pub const fn get_total_pages(&self) -> usize {
111        self.total_pages
112    }
113
114    /// Number of items per page.
115    ///
116    /// * If the value is `0`, it means **all items in a single page**.
117    #[inline]
118    pub const fn get_items_per_page(&self) -> usize {
119        self.items_per_page
120    }
121
122    /// Get total number of items.
123    #[inline]
124    pub const fn get_total_items(&self) -> usize {
125        self.total_items
126    }
127}