Skip to main content

rust_webx_core/
pagination.rs

1//! Pagination types for list endpoints.
2
3use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, Deserialize)]
6pub struct PagedRequest {
7    #[serde(default = "default_page")]
8    pub page: u32,
9    #[serde(default = "default_page_size")]
10    pub page_size: u32,
11}
12
13fn default_page() -> u32 {
14    1
15}
16fn default_page_size() -> u32 {
17    20
18}
19
20impl Default for PagedRequest {
21    fn default() -> Self {
22        Self {
23            page: 1,
24            page_size: 20,
25        }
26    }
27}
28
29impl PagedRequest {
30    pub fn new(page: u32, page_size: u32) -> Self {
31        Self { page, page_size }
32    }
33
34    pub fn offset(&self) -> u32 {
35        (self.page.saturating_sub(1)).saturating_mul(self.page_size)
36    }
37
38    pub fn clamped(mut self) -> Self {
39        self.page = self.page.max(1);
40        self.page_size = self.page_size.clamp(1, 100);
41        self
42    }
43}
44
45#[derive(Debug, Clone, Serialize)]
46pub struct PagedResponse<T: Serialize> {
47    pub items: Vec<T>,
48    pub total: u64,
49    pub page: u32,
50    pub page_size: u32,
51    pub total_pages: u32,
52}
53
54impl<T: Serialize> PagedResponse<T> {
55    pub fn new(items: Vec<T>, total: u64, page: u32, page_size: u32) -> Self {
56        let total_pages = if page_size > 0 {
57            total.div_ceil(page_size as u64) as u32
58        } else {
59            0
60        };
61        Self {
62            items,
63            total,
64            page,
65            page_size,
66            total_pages,
67        }
68    }
69
70    pub fn from_request(items: Vec<T>, total: u64, req: &PagedRequest) -> Self {
71        Self::new(items, total, req.page, req.page_size)
72    }
73}