reinhardt_views/viewsets/
pagination_support.rs1use async_trait::async_trait;
6use reinhardt_core::pagination::{
7 CursorPagination, LimitOffsetPagination, PageNumberPagination, PaginatedResponse, Paginator,
8};
9use reinhardt_http::{Request, Result};
10use serde::Serialize;
11
12#[derive(Debug, Clone)]
14pub enum PaginationConfig {
15 PageNumber {
17 page_size: usize,
19 max_page_size: Option<usize>,
21 },
22 LimitOffset {
24 default_limit: usize,
26 max_limit: Option<usize>,
28 },
29 Cursor {
31 page_size: usize,
33 ordering_field: String,
35 },
36 None,
38}
39
40impl Default for PaginationConfig {
41 fn default() -> Self {
42 Self::PageNumber {
43 page_size: 10,
44 max_page_size: Some(100),
45 }
46 }
47}
48
49impl PaginationConfig {
50 pub fn page_number(page_size: usize, max_page_size: Option<usize>) -> Self {
60 Self::PageNumber {
61 page_size,
62 max_page_size,
63 }
64 }
65
66 pub fn limit_offset(default_limit: usize, max_limit: Option<usize>) -> Self {
76 Self::LimitOffset {
77 default_limit,
78 max_limit,
79 }
80 }
81
82 pub fn cursor(page_size: usize, ordering_field: impl Into<String>) -> Self {
92 Self::Cursor {
93 page_size,
94 ordering_field: ordering_field.into(),
95 }
96 }
97
98 pub fn none() -> Self {
108 Self::None
109 }
110}
111
112#[async_trait]
114pub trait PaginatedViewSet: Send + Sync {
115 fn get_pagination_config(&self) -> Option<PaginationConfig> {
119 Some(PaginationConfig::default())
120 }
121
122 async fn paginate_queryset<T: Serialize + Clone + Send + Sync>(
126 &self,
127 items: Vec<T>,
128 request: &Request,
129 ) -> Result<PaginatedResponse<T>> {
130 let config = self.get_pagination_config().unwrap_or_default();
131
132 let query_string = request.uri.query().unwrap_or("");
134 let base_url = request
135 .uri
136 .path_and_query()
137 .map(|pq| pq.path())
138 .unwrap_or("/");
139
140 match config {
141 PaginationConfig::PageNumber {
142 page_size,
143 max_page_size,
144 } => {
145 let mut paginator = PageNumberPagination::new().page_size(page_size);
146 if let Some(max) = max_page_size {
147 paginator = paginator.max_page_size(max);
148 }
149 paginator.paginate(&items, Some(query_string), base_url)
150 }
151 PaginationConfig::LimitOffset {
152 default_limit,
153 max_limit,
154 } => {
155 let mut paginator = LimitOffsetPagination::new().default_limit(default_limit);
156 if let Some(max) = max_limit {
157 paginator = paginator.max_limit(max);
158 }
159 paginator.paginate(&items, Some(query_string), base_url)
160 }
161 PaginationConfig::Cursor {
162 page_size,
163 ordering_field: _,
164 } => {
165 let paginator = CursorPagination::new().page_size(page_size);
166 paginator.paginate(&items, Some(query_string), base_url)
167 }
168 PaginationConfig::None => {
169 Ok(PaginatedResponse {
171 count: items.len(),
172 next: None,
173 previous: None,
174 results: items,
175 })
176 }
177 }
178 }
179}