use crate::Sort;
use std::{
fmt,
num::NonZeroUsize,
sync::atomic::{AtomicU64, Ordering},
};
static NEXT_REQUEST: AtomicU64 = AtomicU64::new(1);
pub(crate) fn next_revision() -> u64 {
let mut id = NEXT_REQUEST.load(Ordering::Relaxed);
loop {
let next = id.checked_add(1).expect("page request IDs exhausted");
match NEXT_REQUEST.compare_exchange_weak(id, next, Ordering::Relaxed, Ordering::Relaxed) {
Ok(_) => return id,
Err(current) => id = current,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PaginationMode {
Client,
External,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct PageRequest {
pub page: usize,
pub page_size: NonZeroUsize,
pub sort: Option<Sort>,
pub revision: u64,
}
impl PageRequest {
pub fn offset(self) -> usize {
self.page.saturating_mul(self.page_size.get())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct PageState {
pub mode: PaginationMode,
pub page: usize,
pub page_size: NonZeroUsize,
pub page_count: Option<usize>,
pub total_rows: Option<usize>,
pub has_next_page: bool,
pub loaded_rows: usize,
pub loading: bool,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PageError {
NotExternal,
StaleResponse,
WrongRowCount { expected: usize, actual: usize },
}
impl fmt::Display for PageError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::NotExternal => f.write_str("grid is not externally paginated"),
Self::StaleResponse => {
f.write_str("page response is obsolete, foreign, or already applied")
}
Self::WrongRowCount { expected, actual } => write!(
f,
"expected {expected} rows for this page, received {actual}"
),
}
}
}
impl std::error::Error for PageError {}
pub(crate) struct Pagination {
pub mode: PaginationMode,
pub page: usize,
pub size: NonZeroUsize,
pub total: Option<usize>,
pub has_next: bool,
pub revision: u64,
pub loading: bool,
}
impl Pagination {
pub fn count(&self, total: usize) -> usize {
total.div_ceil(self.size.get()).max(1)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum Navigation {
First,
Previous,
Next,
Last,
}