anycms-core 0.5.4

A unified API response library supporting multiple Rust web frameworks
Documentation
use serde::{Deserialize, Serialize};

/// Pagination metadata for list responses
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[cfg_attr(not(feature = "snake-case"), serde(rename_all = "camelCase"))]
#[cfg_attr(feature = "snake-case", serde(rename_all = "snake_case"))]
pub struct ResultPagination {
    pub total: i64,
    pub page: i64,
    pub page_size: i64,
    /// Computed total number of pages
    pub total_pages: i64,
    /// Whether there is a next page
    pub has_next_page: bool,
    /// Whether there is a previous page
    pub has_prev_page: bool,
}

impl Default for ResultPagination {
    fn default() -> Self {
        Self::new(0, 1, 10)
    }
}

// Legacy compatibility: keep current_page accessible as alias for page
impl ResultPagination {
    /// Legacy alias for `page` field (deprecated, use `page` instead)
    #[deprecated(since = "0.5.0", note = "Use `page` field instead")]
    pub fn current_page(&self) -> i64 {
        self.page
    }
}

impl ResultPagination {
    /// Create new pagination metadata
    pub fn new(total: i64, page: i64, page_size: i64) -> Self {
        let total_pages = if page_size <= 0 {
            0
        } else {
            (total + page_size - 1) / page_size
        };
        let has_next_page = page < total_pages;
        let has_prev_page = page > 1;
        Self {
            total,
            page,
            page_size,
            total_pages,
            has_next_page,
            has_prev_page,
        }
    }

    /// Total number of pages
    #[inline]
    pub fn total_pages(&self) -> i64 {
        self.total_pages
    }

    /// Whether there is a next page
    #[inline]
    pub fn has_next(&self) -> bool {
        self.has_next_page
    }

    /// Whether there is a previous page
    #[inline]
    pub fn has_prev(&self) -> bool {
        self.has_prev_page
    }

    /// Calculate the offset for database queries: `(page - 1) * page_size`
    ///
    /// Useful for SQL `OFFSET` clause or ORM pagination.
    ///
    /// # Example
    /// ```
    /// use anycms_core::ResultPagination;
    /// let p = ResultPagination::new(100, 3, 10);
    /// assert_eq!(p.offset(), 20);
    /// ```
    #[inline]
    pub fn offset(&self) -> i64 {
        self.page.saturating_sub(1) * self.page_size
    }

    /// Get the limit for database queries (alias for `page_size`)
    ///
    /// Useful for SQL `LIMIT` clause or ORM pagination.
    #[inline]
    pub fn limit(&self) -> i64 {
        self.page_size
    }

    /// Whether this is the first page (page <= 1)
    #[inline]
    pub fn is_first_page(&self) -> bool {
        self.page <= 1
    }

    /// Whether this is the last page (page >= total_pages)
    #[inline]
    pub fn is_last_page(&self) -> bool {
        self.page >= self.total_pages
    }

    /// Get the next page number, if available
    #[inline]
    pub fn next_page(&self) -> Option<i64> {
        if self.has_next_page {
            Some(self.page + 1)
        } else {
            None
        }
    }

    /// Get the previous page number, if available
    #[inline]
    pub fn prev_page(&self) -> Option<i64> {
        if self.has_prev_page {
            Some(self.page - 1)
        } else {
            None
        }
    }
}