1use serde::Deserialize;
10
11#[derive(Debug, Clone, PartialEq)]
13pub struct Page<T> {
14 pub data: Vec<T>,
16 pub count: u64,
19 pub total: Option<u64>,
22}
23
24impl<T> Page<T> {
25 pub fn len(&self) -> usize {
27 self.data.len()
28 }
29
30 pub fn is_empty(&self) -> bool {
32 self.data.is_empty()
33 }
34
35 pub fn iter(&self) -> std::slice::Iter<'_, T> {
37 self.data.iter()
38 }
39}
40
41impl<T> IntoIterator for Page<T> {
42 type Item = T;
43 type IntoIter = std::vec::IntoIter<T>;
44
45 fn into_iter(self) -> Self::IntoIter {
46 self.data.into_iter()
47 }
48}
49
50impl<'a, T> IntoIterator for &'a Page<T> {
51 type Item = &'a T;
52 type IntoIter = std::slice::Iter<'a, T>;
53
54 fn into_iter(self) -> Self::IntoIter {
55 self.data.iter()
56 }
57}
58
59impl<'de, T: Deserialize<'de>> Deserialize<'de> for Page<T> {
60 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
61 where
62 D: serde::Deserializer<'de>,
63 {
64 #[derive(Deserialize)]
65 #[serde(untagged)]
66 enum Envelope<T> {
67 Wrapped {
68 data: Vec<T>,
69 #[serde(default)]
70 count: Option<u64>,
71 #[serde(default)]
72 total: Option<u64>,
73 },
74 Bare(Vec<T>),
75 }
76
77 Ok(match Envelope::<T>::deserialize(deserializer)? {
78 Envelope::Wrapped { data, count, total } => {
79 let len = data.len() as u64;
80 Page {
81 data,
82 count: count.unwrap_or(len),
83 total,
84 }
85 }
86 Envelope::Bare(data) => {
87 let len = data.len() as u64;
88 Page {
89 data,
90 count: len,
91 total: None,
92 }
93 }
94 })
95 }
96}
97
98#[cfg(test)]
99mod tests {
100 use super::*;
101 use serde_json::json;
102
103 #[test]
104 fn wrapped_envelope_with_count() {
105 let page: Page<serde_json::Value> =
106 serde_json::from_value(json!({"data": [{"id": 1}, {"id": 2}], "count": 2})).unwrap();
107 assert_eq!(page.len(), 2);
108 assert_eq!(page.count, 2);
109 assert_eq!(page.total, None);
110 }
111
112 #[test]
113 fn wrapped_envelope_with_total() {
114 let page: Page<serde_json::Value> =
115 serde_json::from_value(json!({"data": [{"id": 1}], "count": 1, "total": 41})).unwrap();
116 assert_eq!(page.count, 1);
117 assert_eq!(page.total, Some(41));
118 }
119
120 #[test]
121 fn bare_array_synthesizes_count() {
122 let page: Page<serde_json::Value> =
123 serde_json::from_value(json!([{"id": 1}, {"id": 2}, {"id": 3}])).unwrap();
124 assert_eq!(page.count, 3);
125 assert_eq!(page.total, None);
126 }
127}