hyaenidae/server/src/pagination/mod.rs

86 lines
2.4 KiB
Rust
Raw Normal View History

use uuid::Uuid;
pub mod submission;
#[derive(Debug)]
pub(crate) enum PageSource {
NewerThan(Uuid),
OlderThan(Uuid),
}
#[derive(Debug)]
pub(crate) struct Page {
pub(crate) items: Vec<Uuid>,
pub(crate) next: Option<Uuid>,
pub(crate) prev: Option<Uuid>,
pub(crate) reset: bool,
}
pub trait Pagination {
fn from_max<'a>(&'a mut self, max: Uuid) -> Box<dyn DoubleEndedIterator<Item = Uuid> + 'a>;
fn from_min<'a>(&'a mut self, min: Uuid) -> Box<dyn DoubleEndedIterator<Item = Uuid> + 'a>;
fn from_start<'a>(&'a mut self) -> Box<dyn DoubleEndedIterator<Item = Uuid> + 'a>;
}
impl Page {
pub(crate) fn from_pagination(
mut pagination: impl Pagination,
per_page: usize,
source: Option<PageSource>,
) -> Self {
let mut items: Vec<Uuid>;
let mut next = None;
let mut prev = None;
let mut reset = false;
match source {
Some(PageSource::OlderThan(max)) => {
items = pagination.from_max(max).take(per_page + 1).collect();
if let Some(item) = items.get(0) {
prev = Some(*item);
} else {
reset = true;
}
if items.len() == per_page + 1 {
items.pop();
next = Some(items[per_page.saturating_sub(1)]);
}
}
Some(PageSource::NewerThan(min)) => {
let mut tmp_items: Vec<_> = pagination.from_min(min).take(per_page + 2).collect();
if tmp_items.len() == per_page + 2 {
tmp_items.pop();
prev = Some(tmp_items[per_page]);
}
items = tmp_items.into_iter().rev().collect();
items.pop();
if let Some(item) = items.get(items.len().saturating_sub(1)) {
next = Some(*item);
} else {
reset = true;
}
}
None => {
items = pagination.from_start().take(per_page + 1).collect();
if items.len() == per_page + 1 {
items.pop();
next = Some(items[per_page.saturating_sub(1)]);
}
}
}
Page {
items,
next,
prev,
reset,
}
}
}