//! Shared pagination helpers for the public page handlers. use crate::constants; /// Build a sliding window of page numbers for pagination controls. /// /// One definition for every public list page (feed, discover, landing), they /// previously each carried a byte-identical copy, so a tweak to the window /// behavior had to be made in lockstep or silently drift. pub(super) fn build_pagination_range(current_page: u32, total_pages: u32) -> Vec { if total_pages <= constants::PAGINATION_WINDOW_SIZE { (1..=total_pages).collect() } else { let start = current_page.saturating_sub(2).max(1); let end = (start + 4).min(total_pages); let start = end.saturating_sub(4).max(1); (start..=end).collect() } } #[cfg(test)] mod tests { use super::*; #[test] fn pagination_small_total() { assert_eq!(build_pagination_range(1, 3), vec![1, 2, 3]); assert_eq!(build_pagination_range(2, 5), vec![1, 2, 3, 4, 5]); } #[test] fn pagination_large_at_start() { assert_eq!(build_pagination_range(1, 20), vec![1, 2, 3, 4, 5]); assert_eq!(build_pagination_range(2, 20), vec![1, 2, 3, 4, 5]); } #[test] fn pagination_large_at_middle() { assert_eq!(build_pagination_range(10, 20), vec![8, 9, 10, 11, 12]); } #[test] fn pagination_large_at_end() { assert_eq!(build_pagination_range(20, 20), vec![16, 17, 18, 19, 20]); assert_eq!(build_pagination_range(19, 20), vec![16, 17, 18, 19, 20]); } #[test] fn pagination_zero_pages() { assert_eq!(build_pagination_range(1, 0), Vec::::new()); } #[test] fn pagination_single_page() { assert_eq!(build_pagination_range(1, 1), vec![1]); } }