paginator-utils 0.2.2

Shared pagination response structures
Documentation
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize, Debug)]
pub struct PaginatorResponse<T> {
    pub data: Vec<T>,
    pub meta: PaginatorResponseMeta,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct PaginatorResponseMeta {
    pub page: u32,
    pub per_page: u32,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub total: Option<u32>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub total_pages: Option<u32>,
    pub has_next: bool,
    pub has_prev: bool,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub next_cursor: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub prev_cursor: Option<String>,
}

impl PaginatorResponseMeta {
    pub fn new(page: u32, per_page: u32, total: u32) -> Self {
        let total_pages = (total as f32 / per_page as f32).ceil() as u32;
        Self {
            page,
            per_page,
            total: Some(total),
            total_pages: Some(total_pages),
            has_next: page < total_pages,
            has_prev: page > 1,
            next_cursor: None,
            prev_cursor: None,
        }
    }

    pub fn new_without_total(page: u32, per_page: u32, has_next: bool) -> Self {
        Self {
            page,
            per_page,
            total: None,
            total_pages: None,
            has_next,
            has_prev: page > 1,
            next_cursor: None,
            prev_cursor: None,
        }
    }

    pub fn new_with_cursors(
        page: u32,
        per_page: u32,
        total: Option<u32>,
        has_next: bool,
        next_cursor: Option<String>,
        prev_cursor: Option<String>,
    ) -> Self {
        let total_pages = total.map(|t| (t as f32 / per_page as f32).ceil() as u32);
        Self {
            page,
            per_page,
            total,
            total_pages,
            has_next,
            has_prev: page > 1 || prev_cursor.is_some(),
            next_cursor,
            prev_cursor,
        }
    }
}