1use serde::Serialize;
4
5#[derive(Debug, Clone, Serialize)]
7pub struct Paginator<T> {
8 pub items: Vec<T>,
10 pub total: i64,
12 pub per_page: u64,
14 pub current_page: u64,
16 pub last_page: u64,
18}
19
20impl<T> Paginator<T> {
21 pub fn new(items: Vec<T>, total: i64, per_page: u64, current_page: u64) -> Self {
23 let per_page = per_page.max(1);
24 let total_u = total.max(0) as u64;
25 let last_page = if total_u == 0 {
26 1
27 } else {
28 total_u.div_ceil(per_page)
29 };
30 Self {
31 items,
32 total,
33 per_page,
34 current_page: current_page.max(1),
35 last_page,
36 }
37 }
38
39 pub fn has_more_pages(&self) -> bool {
40 self.current_page < self.last_page
41 }
42
43 pub fn has_previous_pages(&self) -> bool {
44 self.current_page > 1
45 }
46
47 pub fn next_page(&self) -> Option<u64> {
48 self.has_more_pages().then(|| self.current_page + 1)
49 }
50
51 pub fn previous_page(&self) -> Option<u64> {
52 self.has_previous_pages().then(|| self.current_page - 1)
53 }
54
55 pub fn count(&self) -> usize {
57 self.items.len()
58 }
59
60 pub fn from(&self) -> Option<u64> {
62 if self.items.is_empty() {
63 None
64 } else {
65 Some((self.current_page - 1) * self.per_page + 1)
66 }
67 }
68
69 pub fn to(&self) -> Option<u64> {
70 if self.items.is_empty() {
71 None
72 } else {
73 Some((self.current_page - 1) * self.per_page + self.items.len() as u64)
74 }
75 }
76
77 pub fn is_empty(&self) -> bool {
78 self.items.is_empty()
79 }
80
81 pub fn map<U, F: FnMut(T) -> U>(self, mut f: F) -> Paginator<U> {
83 Paginator {
84 items: self.items.into_iter().map(&mut f).collect(),
85 total: self.total,
86 per_page: self.per_page,
87 current_page: self.current_page,
88 last_page: self.last_page,
89 }
90 }
91}