2021-01-22 05:47:47 +00:00
|
|
|
use uuid::Uuid;
|
|
|
|
|
2021-01-25 04:09:48 +00:00
|
|
|
#[derive(Debug)]
|
2021-01-22 05:47:47 +00:00
|
|
|
pub(crate) enum PageSource {
|
|
|
|
NewerThan(Uuid),
|
|
|
|
OlderThan(Uuid),
|
|
|
|
}
|
|
|
|
|
2021-01-26 02:38:05 +00:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub(crate) struct PageNum {
|
|
|
|
pub(crate) page: usize,
|
|
|
|
}
|
|
|
|
|
2021-01-25 04:09:48 +00:00
|
|
|
#[derive(Debug)]
|
2021-01-22 05:47:47 +00:00
|
|
|
pub(crate) struct Page {
|
|
|
|
pub(crate) items: Vec<Uuid>,
|
|
|
|
pub(crate) next: Option<Uuid>,
|
|
|
|
pub(crate) prev: Option<Uuid>,
|
|
|
|
pub(crate) reset: bool,
|
|
|
|
}
|
|
|
|
|
2021-01-26 02:38:05 +00:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub(crate) struct SearchPage {
|
|
|
|
pub(crate) items: Vec<Uuid>,
|
|
|
|
pub(crate) next: Option<usize>,
|
|
|
|
pub(crate) prev: Option<usize>,
|
|
|
|
pub(crate) term: String,
|
|
|
|
}
|
|
|
|
|
2021-01-22 05:47:47 +00:00
|
|
|
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>;
|
|
|
|
}
|
|
|
|
|
2021-01-26 02:38:05 +00:00
|
|
|
pub trait SearchPagination {
|
|
|
|
fn from_term<'a>(&'a mut self, term: &'a str)
|
|
|
|
-> Box<dyn DoubleEndedIterator<Item = Uuid> + 'a>;
|
|
|
|
}
|
|
|
|
|
2021-01-22 05:47:47 +00:00
|
|
|
impl Page {
|
|
|
|
pub(crate) fn from_pagination(
|
|
|
|
mut pagination: impl Pagination,
|
|
|
|
per_page: usize,
|
|
|
|
source: Option<PageSource>,
|
|
|
|
) -> Self {
|
2021-01-24 04:04:27 +00:00
|
|
|
let mut items: Vec<Uuid>;
|
2021-01-22 05:47:47 +00:00
|
|
|
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();
|
2021-01-24 04:04:27 +00:00
|
|
|
prev = Some(tmp_items[per_page]);
|
2021-01-22 05:47:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-01-26 02:38:05 +00:00
|
|
|
|
|
|
|
impl SearchPage {
|
|
|
|
pub(crate) fn from_pagination(
|
|
|
|
mut pagination: impl SearchPagination,
|
|
|
|
per_page: usize,
|
|
|
|
term: String,
|
|
|
|
page: Option<PageNum>,
|
|
|
|
) -> Self {
|
|
|
|
let mut items: Vec<Uuid>;
|
|
|
|
let mut next = None;
|
|
|
|
let mut prev = None;
|
|
|
|
|
|
|
|
match page {
|
|
|
|
Some(PageNum { page }) => {
|
2021-02-05 01:13:47 +00:00
|
|
|
let page = page.saturating_sub(1);
|
2021-01-26 02:38:05 +00:00
|
|
|
items = pagination
|
|
|
|
.from_term(&term)
|
|
|
|
.skip(page * per_page)
|
|
|
|
.take(per_page + 1)
|
|
|
|
.collect();
|
|
|
|
if page > 0 {
|
2021-02-05 01:13:47 +00:00
|
|
|
prev = Some(page);
|
2021-01-26 02:38:05 +00:00
|
|
|
}
|
|
|
|
if items.len() == per_page + 1 {
|
|
|
|
items.pop();
|
2021-02-05 01:13:47 +00:00
|
|
|
next = Some(page + 2);
|
2021-01-26 02:38:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
None => {
|
|
|
|
items = pagination.from_term(&term).take(per_page + 1).collect();
|
|
|
|
if items.len() == per_page + 1 {
|
|
|
|
items.pop();
|
2021-02-05 01:13:47 +00:00
|
|
|
next = Some(2);
|
2021-01-26 02:38:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SearchPage {
|
|
|
|
items,
|
|
|
|
next,
|
|
|
|
prev,
|
|
|
|
term,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|