use async_graphql::SimpleObject;
#[derive(Debug, Clone, SimpleObject)]
pub struct PageInfo {
pub has_next_page: bool,
pub has_previous_page: bool,
pub total_pages: u64,
}
pub fn page_info(total_count: u64, page: u64, per_page: u64) -> PageInfo {
let total_pages = if per_page == 0 {
0
} else {
(total_count + per_page - 1) / per_page
};
PageInfo {
has_next_page: page < total_pages,
has_previous_page: page > 1,
total_pages,
}
}
#[derive(Debug, Clone)]
pub struct Connection<T> {
pub items: Vec<T>,
pub total_count: u64,
pub page_info: PageInfo,
}
impl<T> Connection<T> {
pub fn new(items: Vec<T>, total_count: u64, page: u64, per_page: u64) -> Self {
Self {
items,
total_count,
page_info: page_info(total_count, page, per_page),
}
}
}
pub trait IntoConnection<T> {
fn into_connection(self, page: u64, per_page: u64) -> Connection<T>;
}
impl<T> IntoConnection<T> for (Vec<T>, u64) {
fn into_connection(self, page: u64, per_page: u64) -> Connection<T> {
Connection::new(self.0, self.1, page, per_page)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_page_info_first_page() {
let info = page_info(100, 1, 10);
assert!(info.has_next_page);
assert!(!info.has_previous_page);
assert_eq!(info.total_pages, 10);
}
#[test]
fn test_page_info_middle_page() {
let info = page_info(100, 5, 10);
assert!(info.has_next_page);
assert!(info.has_previous_page);
assert_eq!(info.total_pages, 10);
}
#[test]
fn test_page_info_last_page() {
let info = page_info(100, 10, 10);
assert!(!info.has_next_page);
assert!(info.has_previous_page);
assert_eq!(info.total_pages, 10);
}
#[test]
fn test_page_info_single_page() {
let info = page_info(5, 1, 10);
assert!(!info.has_next_page);
assert!(!info.has_previous_page);
assert_eq!(info.total_pages, 1);
}
#[test]
fn test_page_info_empty() {
let info = page_info(0, 1, 10);
assert!(!info.has_next_page);
assert!(!info.has_previous_page);
assert_eq!(info.total_pages, 0);
}
#[test]
fn test_page_info_zero_per_page() {
let info = page_info(100, 1, 0);
assert_eq!(info.total_pages, 0);
}
#[test]
fn test_page_info_partial_last_page() {
let info = page_info(95, 10, 10);
assert!(!info.has_next_page);
assert!(info.has_previous_page);
assert_eq!(info.total_pages, 10);
}
#[test]
fn test_connection_new() {
let items = vec![1, 2, 3];
let conn = Connection::new(items, 30, 1, 10);
assert_eq!(conn.items.len(), 3);
assert_eq!(conn.total_count, 30);
assert!(conn.page_info.has_next_page);
}
#[test]
fn test_into_connection() {
let result: (Vec<i32>, u64) = (vec![1, 2, 3], 30);
let conn = result.into_connection(1, 10);
assert_eq!(conn.items.len(), 3);
assert_eq!(conn.total_count, 30);
assert!(conn.page_info.has_next_page);
}
}