use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Pagination {
pub page: u32,
pub per_page: u32,
pub total: Option<u64>,
pub total_pages: Option<u32>,
}
impl Pagination {
pub fn new(page: u32, per_page: u32) -> Self {
Self {
page,
per_page,
total: None,
total_pages: None,
}
}
pub fn offset(&self) -> u32 {
(self.page - 1) * self.per_page
}
pub fn limit(&self) -> u32 {
self.per_page
}
pub fn set_total(&mut self, total: u64) {
self.total = Some(total);
self.total_pages = Some(((total as f64) / (self.per_page as f64)).ceil() as u32);
}
pub fn has_next(&self) -> bool {
if let (Some(total_pages), Some(current_page)) = (self.total_pages, Some(self.page)) {
current_page < total_pages
} else {
false
}
}
pub fn has_prev(&self) -> bool {
self.page > 1
}
pub fn start_item(&self) -> u32 {
(self.page - 1) * self.per_page + 1
}
pub fn end_item(&self) -> u32 {
self.page * self.per_page
}
pub fn next_page(&self) -> Option<u32> {
if self.has_next() {
Some(self.page + 1)
} else {
None
}
}
pub fn prev_page(&self) -> Option<u32> {
if self.has_prev() {
Some(self.page - 1)
} else {
None
}
}
}
impl Default for Pagination {
fn default() -> Self {
Self::new(1, 20)
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PaginatedResult<T> {
pub data: Vec<T>,
pub pagination: Pagination,
}
impl<T> PaginatedResult<T> {
pub fn new(data: Vec<T>, pagination: Pagination) -> Self {
Self { data, pagination }
}
pub fn with_total(data: Vec<T>, mut pagination: Pagination, total: u64) -> Self {
pagination.set_total(total);
Self { data, pagination }
}
pub fn data(&self) -> &[T] {
&self.data
}
pub fn pagination(&self) -> &Pagination {
&self.pagination
}
pub fn len(&self) -> usize {
self.data.len()
}
pub fn is_empty(&self) -> bool {
self.data.is_empty()
}
pub fn map<U, F>(self, f: F) -> PaginatedResult<U>
where
F: FnMut(T) -> U,
{
PaginatedResult {
data: self.data.into_iter().map(f).collect(),
pagination: self.pagination,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CursorPagination {
pub cursor: Option<String>,
pub limit: u32,
pub include_cursor: bool,
pub has_next: bool,
pub has_prev: bool,
pub next_cursor: Option<String>,
pub prev_cursor: Option<String>,
pub total: Option<u64>,
}
impl CursorPagination {
pub fn new(limit: u32) -> Self {
Self {
cursor: None,
limit,
include_cursor: false,
has_next: false,
has_prev: false,
next_cursor: None,
prev_cursor: None,
total: None,
}
}
pub fn with_cursor(limit: u32, cursor: Option<String>) -> Self {
let has_prev = cursor.is_some();
Self {
cursor,
limit,
include_cursor: false,
has_next: false,
has_prev,
next_cursor: None,
prev_cursor: None,
total: None,
}
}
pub fn with_cursor_old(cursor: String, limit: u32) -> Self {
Self {
cursor: Some(cursor),
limit,
include_cursor: false,
has_next: false,
has_prev: true,
next_cursor: None,
prev_cursor: None,
total: None,
}
}
pub fn set_cursor(&mut self, cursor: Option<String>) {
self.cursor = cursor;
}
pub fn limit(&self) -> u32 {
self.limit
}
}
impl Default for CursorPagination {
fn default() -> Self {
Self::new(20)
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CursorPaginatedResult<T> {
pub data: Vec<T>,
pub pagination: CursorPagination,
}
impl<T> CursorPaginatedResult<T> {
pub fn new(data: Vec<T>, pagination: CursorPagination) -> Self {
Self { data, pagination }
}
pub fn data(&self) -> &[T] {
&self.data
}
pub fn pagination(&self) -> &CursorPagination {
&self.pagination
}
}