1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
//! Template model for pagination bar.
use std::num::NonZeroU64;
/// Pagination template fields.
#[derive(Serialize, Copy, Clone, Debug)]
pub struct PaginationInfo {
// first field excluded, first page is always page 1
/// Flag to include left side ellipsis/separator.
left_sep: bool,
/// Previous page number (current - 1).
prev: u64,
/// Current page number.
current: NonZeroU64,
/// Next page number (current + 1).
next: u64,
/// Flag to include right side ellipsis/separator
right_sep: bool,
/// Last page number.
last: u64,
}
impl PaginationInfo {
/// Create a new pagination info object if there are enough results to
/// require multiple pages.
fn new_inner(items: u64, per_page: u64, current_page: NonZeroU64) -> Option<Self> {
// Calculate the number of pages required.
let pages_required: u64 = items / per_page + 1;
if pages_required <= 1 {
// No pagination if there is only one page.
None
} else {
Some(PaginationInfo {
// include left separator if there are pages between
left_sep: (current_page.get() - 1) > 2,
// If we're currently on the first page this will be hidden.
prev: current_page.get() - 1,
current: current_page,
// If we're currently on the last page this will be hidden.
next: current_page.get() + 1,
// similar with right separator,
right_sep: current_page.get() + 1 < pages_required - 1,
last: pages_required,
})
}
}
/// Create a new pagination object with 1 indexed page numbers.
/// Return [`Option::None`] if there is only one page.
/// ## Panics:
/// - If the `current_page` is 0.
pub fn new(items: u64, per_page: u64, current_page: u64) -> Option<Self> {
let converted = NonZeroU64::new(current_page).expect("current_page > 0");
Self::new_inner(items, per_page, converted)
}
}