Skip to main content

headless_lms_server/controllers/helpers/
pagination.rs

1//! A page of rows plus the total count, in the shape every paginated admin/teacher list endpoint
2//! returns.
3
4use utoipa::ToSchema;
5
6use crate::prelude::*;
7
8#[derive(Debug, Serialize, Deserialize, PartialEq, Clone, ToSchema)]
9pub struct Page<T: ToSchema + 'static> {
10    pub data: Vec<T>,
11    pub total_count: i64,
12    pub total_pages: u32,
13}
14
15impl<T: ToSchema + 'static> Page<T> {
16    /// `total_count` must come from the same query as `data` (e.g. a `COUNT(*) OVER ()` column),
17    /// not a separate count query, or a page and its total can disagree under concurrent writes.
18    pub fn new(pagination: Pagination, data: Vec<T>, total_count: i64) -> Self {
19        Self {
20            data,
21            total_count,
22            total_pages: pagination.total_pages(u32::try_from(total_count).unwrap_or(u32::MAX)),
23        }
24    }
25}
26
27/// Parses the `page`/`limit` query parameters every list endpoint accepts, defaulting `limit` to
28/// `default_limit` when absent.
29pub fn parse_pagination(
30    page: Option<u32>,
31    limit: Option<u32>,
32    default_limit: u32,
33) -> Result<Pagination, ControllerError> {
34    Pagination::new(page.unwrap_or(1), limit.unwrap_or(default_limit))
35        .map_err(|e| controller_err!(BadRequest, e.to_string()))
36}