Skip to main content

systemprompt_models/api/
pagination.rs

1//! Pagination parameters and page-info responses for list endpoints.
2//!
3//! Copyright (c) systemprompt.io — Business Source License 1.1.
4//! See <https://systemprompt.io> for licensing details.
5
6use serde::{Deserialize, Serialize};
7
8#[derive(Debug, Clone, Serialize, Deserialize)]
9pub struct PaginationInfo {
10    pub total: i64,
11
12    pub page: i32,
13
14    pub per_page: i32,
15
16    pub total_pages: i32,
17
18    pub has_next: bool,
19
20    pub has_prev: bool,
21
22    pub next_url: Option<String>,
23
24    pub prev_url: Option<String>,
25}
26
27impl PaginationInfo {
28    pub fn new(total: i64, page: i32, per_page: i32) -> Self {
29        let per_page_i64 = i64::from(per_page);
30        let total_pages =
31            i32::try_from((total + per_page_i64 - 1) / per_page_i64).unwrap_or(i32::MAX);
32        let has_next = page < total_pages;
33        let has_prev = page > 1;
34
35        Self {
36            total,
37            page,
38            per_page,
39            total_pages,
40            has_next,
41            has_prev,
42            next_url: None,
43            prev_url: None,
44        }
45    }
46
47    pub fn with_base_url(mut self, base_url: &str) -> Self {
48        if self.has_next {
49            self.next_url = Some(format!(
50                "{}?page={}&per_page={}",
51                base_url,
52                self.page + 1,
53                self.per_page
54            ));
55        }
56        if self.has_prev {
57            self.prev_url = Some(format!(
58                "{}?page={}&per_page={}",
59                base_url,
60                self.page - 1,
61                self.per_page
62            ));
63        }
64        self
65    }
66}
67
68#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
69pub struct PaginationParams {
70    #[serde(default = "default_page")]
71    pub page: i32,
72
73    #[serde(default = "default_per_page")]
74    pub per_page: i32,
75}
76
77const fn default_page() -> i32 {
78    1
79}
80
81const fn default_per_page() -> i32 {
82    20
83}
84
85impl Default for PaginationParams {
86    fn default() -> Self {
87        Self {
88            page: default_page(),
89            per_page: default_per_page(),
90        }
91    }
92}
93
94impl PaginationParams {
95    pub const fn offset(&self) -> i32 {
96        (self.page - 1) * self.per_page
97    }
98
99    pub const fn limit(&self) -> i32 {
100        self.per_page
101    }
102}
103
104#[derive(Debug, Clone, Copy, Default, Deserialize, Serialize)]
105#[serde(rename_all = "lowercase")]
106pub enum SortOrder {
107    #[default]
108    Asc,
109    Desc,
110}
111
112#[derive(Debug, Clone, Serialize, Deserialize)]
113pub struct SortParams {
114    pub sort_by: Option<String>,
115
116    #[serde(default)]
117    pub sort_order: SortOrder,
118}
119
120#[derive(Debug, Clone, Serialize, Deserialize)]
121pub struct SearchQuery {
122    pub search: Option<String>,
123    pub sort_by: Option<String>,
124    pub sort_dir: Option<String>,
125}
126
127#[derive(Debug, Clone, Serialize, Deserialize)]
128pub struct ApiQuery {
129    #[serde(flatten)]
130    pub pagination: PaginationParams,
131
132    #[serde(flatten)]
133    pub search: SearchQuery,
134}