Skip to main content

queryweave_api/
page.rs

1//! A page of items, as returned by a paginated query.
2
3// Scoped to this module: a derive's output is a separate item, out of reach of
4// an attribute on the struct.
5#![cfg_attr(
6    feature = "utoipa",
7    allow(
8        clippy::option_if_let_else,
9        reason = "utoipa's `ToSchema` expands the generic `items` field's schema to an if-let/else"
10    )
11)]
12
13// Unbounded: each integration's derive bounds its own impl (e.g. `Serialize`
14// for `T: Serialize`). Not part of the doc comment, which utoipa publishes.
15/// A page of items, as returned by a paginated query.
16#[derive(Debug, Clone)]
17#[cfg_attr(feature = "serde", derive(serde::Serialize))]
18#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
19#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
20pub struct PageDto<T> {
21    /// The page returned (0 based), as requested.
22    pub page: Option<u32>,
23    /// The number of items per page, as requested.
24    pub page_size: Option<u32>,
25    /// The number of pages (none without a page size).
26    pub total_pages: Option<u32>,
27    /// The number of items over every page.
28    pub total_items: u32,
29    /// The items of the page.
30    pub items: Vec<T>,
31}
32
33impl<T> PageDto<T> {
34    /// A page of `items`, out of `total_items`, computing the number of pages.
35    #[must_use]
36    pub fn new(page: Option<u32>, page_size: Option<u32>, total_items: u32, items: Vec<T>) -> Self {
37        // A zero page size has no page count (and must not divide by zero).
38        let total_pages = page_size
39            .filter(|&page_size| page_size != 0)
40            .map(|page_size| total_items.div_ceil(page_size));
41
42        Self {
43            page,
44            page_size,
45            total_pages,
46            total_items,
47            items,
48        }
49    }
50}