use super::cursor::Cursor;
#[derive(Debug, Clone, Default, PartialEq, Eq)]
#[non_exhaustive]
pub struct PageInfo {
pub has_next: bool,
pub has_prev: bool,
pub next_cursor: Option<String>,
pub prev_cursor: Option<String>,
pub total: Option<u64>,
}
impl PageInfo {
#[must_use]
pub const fn new(count: usize, limit: usize) -> Self {
Self {
has_next: count >= limit,
has_prev: false,
next_cursor: None,
prev_cursor: None,
total: None,
}
}
#[must_use]
pub const fn with_has_prev(mut self, has_prev: bool) -> Self {
self.has_prev = has_prev;
self
}
#[must_use]
pub fn with_next_cursor(mut self, cursor: Option<String>) -> Self {
self.next_cursor = cursor;
if self.next_cursor.is_some() {
self.has_next = true;
}
self
}
#[must_use]
pub fn with_prev_cursor(mut self, cursor: Option<String>) -> Self {
self.prev_cursor = cursor;
if self.prev_cursor.is_some() {
self.has_prev = true;
}
self
}
#[must_use]
pub const fn with_total(mut self, total: u64) -> Self {
self.total = Some(total);
self
}
#[allow(clippy::single_option_map)] pub fn cursor_from<T, F>(item: Option<&T>, builder: F) -> Option<String>
where
F: FnOnce(&T) -> Cursor,
{
item.map(|item| builder(item).encode())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_page_info_basic() {
let info = PageInfo::new(20, 20);
assert!(info.has_next);
assert!(!info.has_prev);
let info = PageInfo::new(15, 20);
assert!(!info.has_next);
}
#[test]
fn test_page_info_with_cursors() {
let info = PageInfo::new(20, 20)
.with_next_cursor(Some("abc".to_string()))
.with_prev_cursor(Some("xyz".to_string()))
.with_total(100);
assert!(info.has_next);
assert!(info.has_prev);
assert_eq!(info.next_cursor, Some("abc".to_string()));
assert_eq!(info.prev_cursor, Some("xyz".to_string()));
assert_eq!(info.total, Some(100));
}
}