use std::time::{Duration, SystemTime};
use crate::pagination::encode_cursor;
use crate::tools::PaginationArgs;
pub(crate) fn duration_to_ms(duration: Duration) -> u64 {
duration.as_millis().try_into().unwrap_or(u64::MAX)
}
pub(crate) fn current_epoch_ms() -> u64 {
SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
.map(duration_to_ms)
.unwrap_or(0)
}
pub(crate) fn paginate<'a, T>(
items: &'a [T],
pagination: &PaginationArgs,
) -> (&'a [T], Option<String>) {
if items.is_empty() {
return (&[], None);
}
let start = pagination.offset.min(items.len());
let end = (start + pagination.size).min(items.len());
let next = if end < items.len() {
Some(encode_cursor(end))
} else {
None
};
(&items[start..end], next)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_duration_to_ms_zero() {
let duration = Duration::from_secs(0);
assert_eq!(duration_to_ms(duration), 0);
}
#[test]
fn test_duration_to_ms_one_second() {
let duration = Duration::from_secs(1);
assert_eq!(duration_to_ms(duration), 1000);
}
#[test]
fn test_duration_to_ms_with_millis() {
let duration = Duration::from_millis(1234);
assert_eq!(duration_to_ms(duration), 1234);
}
#[test]
fn test_duration_to_ms_one_hour() {
let duration = Duration::from_secs(3600);
assert_eq!(duration_to_ms(duration), 3_600_000);
}
#[test]
fn test_duration_to_ms_with_nanos() {
let duration = Duration::from_micros(500);
assert_eq!(duration_to_ms(duration), 0);
}
#[test]
fn test_duration_to_ms_large_value() {
let duration = Duration::from_secs(365 * 24 * 3600);
assert_eq!(duration_to_ms(duration), 31_536_000_000);
}
#[test]
fn test_current_epoch_ms_is_reasonable() {
let now = current_epoch_ms();
assert!(now > 1_577_836_800_000);
assert!(now < 4_102_444_800_000);
}
#[test]
fn test_paginate_empty_slice() {
let items: Vec<i32> = vec![];
let pagination = PaginationArgs {
offset: 0,
size: 10,
};
let (result, next) = paginate(&items, &pagination);
assert!(result.is_empty());
assert!(next.is_none());
}
#[test]
fn test_paginate_single_page() {
let items = vec![1, 2, 3, 4, 5];
let pagination = PaginationArgs {
offset: 0,
size: 10,
};
let (result, next) = paginate(&items, &pagination);
assert_eq!(result, &[1, 2, 3, 4, 5]);
assert!(next.is_none());
}
#[test]
fn test_paginate_first_page() {
let items = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let pagination = PaginationArgs { offset: 0, size: 3 };
let (result, next) = paginate(&items, &pagination);
assert_eq!(result, &[1, 2, 3]);
assert!(next.is_some());
}
#[test]
fn test_paginate_middle_page() {
let items = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let pagination = PaginationArgs { offset: 3, size: 3 };
let (result, next) = paginate(&items, &pagination);
assert_eq!(result, &[4, 5, 6]);
assert!(next.is_some());
}
#[test]
fn test_paginate_last_page() {
let items = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let pagination = PaginationArgs { offset: 9, size: 3 };
let (result, next) = paginate(&items, &pagination);
assert_eq!(result, &[10]);
assert!(next.is_none());
}
#[test]
fn test_paginate_offset_beyond_items() {
let items = vec![1, 2, 3];
let pagination = PaginationArgs {
offset: 100,
size: 10,
};
let (result, next) = paginate(&items, &pagination);
assert!(result.is_empty());
assert!(next.is_none());
}
#[test]
fn test_paginate_exact_page_boundary() {
let items = vec![1, 2, 3, 4, 5, 6];
let pagination = PaginationArgs { offset: 0, size: 3 };
let (result, next) = paginate(&items, &pagination);
assert_eq!(result, &[1, 2, 3]);
assert!(next.is_some());
let pagination2 = PaginationArgs { offset: 3, size: 3 };
let (result2, next2) = paginate(&items, &pagination2);
assert_eq!(result2, &[4, 5, 6]);
assert!(next2.is_none());
}
#[test]
fn test_paginate_size_one() {
let items = vec![1, 2, 3];
let pagination = PaginationArgs { offset: 0, size: 1 };
let (result, next) = paginate(&items, &pagination);
assert_eq!(result, &[1]);
assert!(next.is_some());
}
#[test]
fn test_paginate_with_strings() {
let items = vec!["a", "b", "c", "d"];
let pagination = PaginationArgs { offset: 1, size: 2 };
let (result, next) = paginate(&items, &pagination);
assert_eq!(result, &["b", "c"]);
assert!(next.is_some());
}
}