api_tools/value_objects/
pagination.rs1pub const PAGINATION_MIN_LIMIT: u32 = 10;
5
6pub const PAGINATION_MAX_LIMIT: u32 = 500;
8
9pub const PAGINATION_DEFAULT_LIMIT: u32 = 200;
11
12#[derive(Debug, Clone, PartialEq, Eq)]
13pub struct Pagination {
14 page: u32,
15 limit: u32,
16 max_limit: Option<u32>,
17}
18
19impl Pagination {
20 pub fn new(page: u32, limit: u32, max_limit: Option<u32>) -> Self {
54 let page = if page == 0 { 1 } else { page };
55
56 let mut max = max_limit.unwrap_or(PAGINATION_MAX_LIMIT);
57
58 if max > PAGINATION_MAX_LIMIT {
59 max = PAGINATION_MAX_LIMIT;
60 }
61
62 let limit = if limit > max {
63 max
64 } else if limit < PAGINATION_MIN_LIMIT {
65 PAGINATION_MIN_LIMIT
66 } else {
67 limit
68 };
69
70 Self { page, limit, max_limit }
71 }
72
73 pub fn page(&self) -> u32 {
75 self.page
76 }
77
78 pub fn limit(&self) -> u32 {
80 self.limit
81 }
82
83 pub fn set_max_limit(&mut self, max_limit: u32) {
85 let max_limit = max_limit.clamp(PAGINATION_MIN_LIMIT, PAGINATION_MAX_LIMIT);
86 self.max_limit = Some(max_limit);
87 }
88}
89
90impl Default for Pagination {
91 fn default() -> Self {
93 let default = if PAGINATION_DEFAULT_LIMIT > PAGINATION_MAX_LIMIT {
94 PAGINATION_MAX_LIMIT
95 } else {
96 PAGINATION_DEFAULT_LIMIT
97 };
98 Self::new(1, default, None)
99 }
100}
101
102#[derive(Debug, Clone, PartialEq)]
104
105pub struct PaginationResponse {
106 pub page: u32,
107 pub limit: u32,
108 pub total: i64,
109}
110
111impl PaginationResponse {
112 pub fn new(page: u32, limit: u32, total: i64) -> Self {
114 Self { page, limit, total }
115 }
116}
117
118#[cfg(test)]
119mod test {
120 use super::*;
121
122 #[test]
123 fn test_set_max_limit() {
124 let mut pagination = Pagination::default();
125 assert_eq!(pagination.max_limit, None);
126
127 pagination.set_max_limit(100);
128 assert_eq!(pagination.max_limit, Some(100));
129
130 pagination.set_max_limit(300);
131 assert_eq!(pagination.max_limit, Some(300));
132
133 pagination.set_max_limit(5);
134 assert_eq!(pagination.max_limit, Some(PAGINATION_MIN_LIMIT));
135
136 pagination.set_max_limit(600);
137 assert_eq!(pagination.max_limit, Some(PAGINATION_MAX_LIMIT));
138 }
139
140 #[test]
141 fn test_default() {
142 let pagination = Pagination::default();
143 assert_eq!(pagination.page(), 1);
144 assert_eq!(pagination.limit(), PAGINATION_DEFAULT_LIMIT);
145 assert_eq!(pagination.max_limit, None);
146 }
147
148 #[test]
149 fn new_clamps_zero_page_to_one() {
150 let p = Pagination::new(0, 100, None);
151 assert_eq!(p.page(), 1);
152 }
153
154 #[test]
155 fn new_clamps_limit_below_min_to_pagination_min_limit() {
156 let p = Pagination::new(1, 1, None);
157 assert_eq!(p.limit(), PAGINATION_MIN_LIMIT);
158 }
159
160 #[test]
161 fn new_clamps_limit_above_max_to_pagination_max_limit() {
162 let p = Pagination::new(1, PAGINATION_MAX_LIMIT + 100, None);
163 assert_eq!(p.limit(), PAGINATION_MAX_LIMIT);
164 }
165
166 #[test]
167 fn new_caps_max_limit_argument_at_pagination_max_limit() {
168 let p = Pagination::new(1, 10_000, Some(10_000));
171 assert_eq!(p.limit(), PAGINATION_MAX_LIMIT);
172 }
173
174 #[test]
175 fn new_respects_a_smaller_custom_max_limit() {
176 let p = Pagination::new(1, 1_000, Some(100));
177 assert_eq!(p.limit(), 100);
178 }
179
180 #[test]
181 fn pagination_response_new_stores_all_fields() {
182 let r = PaginationResponse::new(2, 50, 1_234);
183 assert_eq!(r.page, 2);
184 assert_eq!(r.limit, 50);
185 assert_eq!(r.total, 1_234);
186 }
187}