paginator_utils/
response.rs1use serde::{Deserialize, Serialize};
2
3#[derive(Serialize, Deserialize, Debug)]
4pub struct PaginatorResponse<T> {
5 pub data: Vec<T>,
6 pub meta: PaginatorResponseMeta,
7}
8
9#[derive(Serialize, Deserialize, Debug)]
10pub struct PaginatorResponseMeta {
11 pub page: u32,
12 pub per_page: u32,
13 #[serde(skip_serializing_if = "Option::is_none")]
14 pub total: Option<u32>,
15 #[serde(skip_serializing_if = "Option::is_none")]
16 pub total_pages: Option<u32>,
17 pub has_next: bool,
18 pub has_prev: bool,
19 #[serde(skip_serializing_if = "Option::is_none")]
20 pub next_cursor: Option<String>,
21 #[serde(skip_serializing_if = "Option::is_none")]
22 pub prev_cursor: Option<String>,
23}
24
25impl PaginatorResponseMeta {
26 pub fn new(page: u32, per_page: u32, total: u32) -> Self {
27 let total_pages = (total as f32 / per_page as f32).ceil() as u32;
28 Self {
29 page,
30 per_page,
31 total: Some(total),
32 total_pages: Some(total_pages),
33 has_next: page < total_pages,
34 has_prev: page > 1,
35 next_cursor: None,
36 prev_cursor: None,
37 }
38 }
39
40 pub fn new_without_total(page: u32, per_page: u32, has_next: bool) -> Self {
41 Self {
42 page,
43 per_page,
44 total: None,
45 total_pages: None,
46 has_next,
47 has_prev: page > 1,
48 next_cursor: None,
49 prev_cursor: None,
50 }
51 }
52
53 pub fn new_with_cursors(
54 page: u32,
55 per_page: u32,
56 total: Option<u32>,
57 has_next: bool,
58 next_cursor: Option<String>,
59 prev_cursor: Option<String>,
60 ) -> Self {
61 let total_pages = total.map(|t| (t as f32 / per_page as f32).ceil() as u32);
62 Self {
63 page,
64 per_page,
65 total,
66 total_pages,
67 has_next,
68 has_prev: page > 1 || prev_cursor.is_some(),
69 next_cursor,
70 prev_cursor,
71 }
72 }
73}