uptrakit_web_api_types/
pagination.rs1use serde::{Deserialize, Serialize};
2
3pub const DEFAULT_PER_PAGE: u64 = 20;
4pub const MAX_PER_PAGE: u64 = 1000;
5
6#[derive(Debug, Clone, Serialize, Deserialize)]
8#[cfg_attr(feature = "openapi", derive(utoipa::IntoParams))]
9pub struct PaginationParams {
10 pub page: Option<u64>,
12 pub per_page: Option<u64>,
14}
15
16#[derive(Debug, Clone, Copy)]
18pub struct ResolvedPagination {
19 pub page: u64,
20 pub per_page: u64,
21}
22
23impl PaginationParams {
24 pub fn resolve(&self) -> ResolvedPagination {
25 let page = self.page.unwrap_or(1).max(1);
26 let per_page = self
27 .per_page
28 .unwrap_or(DEFAULT_PER_PAGE)
29 .clamp(1, MAX_PER_PAGE);
30 ResolvedPagination { page, per_page }
31 }
32}
33
34impl ResolvedPagination {
35 pub fn offset(&self) -> u64 {
36 (self.page - 1) * self.per_page
37 }
38
39 pub fn total_pages(&self, total: u64) -> u64 {
40 total.div_ceil(self.per_page)
41 }
42}
43
44#[derive(Debug, Clone, Serialize, Deserialize)]
46#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
47pub struct PaginatedResponse<T> {
48 pub items: Vec<T>,
49 pub total: u64,
50 pub page: u64,
51 pub per_page: u64,
52 pub total_pages: u64,
53}
54
55impl<T> PaginatedResponse<T> {
56 pub fn new(items: Vec<T>, total: u64, pagination: ResolvedPagination) -> Self {
57 Self {
58 items,
59 total,
60 page: pagination.page,
61 per_page: pagination.per_page,
62 total_pages: pagination.total_pages(total),
63 }
64 }
65}