use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ProviderBatch<T> {
pub items: Vec<T>,
pub total_count: i64,
pub has_next_page: bool,
pub next_page_token: Option<String>,
}
impl<T> ProviderBatch<T> {
pub fn new(items: Vec<T>) -> Self {
let count = items.len() as i64;
Self {
items,
total_count: count,
has_next_page: false,
next_page_token: None,
}
}
pub fn with_pagination(
items: Vec<T>,
total_count: i64,
has_next_page: bool,
next_page_token: Option<String>,
) -> Self {
Self {
items,
total_count,
has_next_page,
next_page_token,
}
}
pub fn empty() -> Self {
Self {
items: Vec::new(),
total_count: 0,
has_next_page: false,
next_page_token: None,
}
}
pub fn len(&self) -> usize {
self.items.len()
}
pub fn is_empty(&self) -> bool {
self.items.is_empty()
}
pub fn is_last_page(&self) -> bool {
!self.has_next_page
}
pub fn items(&self) -> &[T] {
&self.items
}
pub fn into_items(self) -> Vec<T> {
self.items
}
pub fn map<U, F>(self, f: F) -> ProviderBatch<U>
where
F: FnMut(T) -> U,
{
ProviderBatch {
items: self.items.into_iter().map(f).collect(),
total_count: self.total_count,
has_next_page: self.has_next_page,
next_page_token: self.next_page_token,
}
}
pub fn filter<F>(self, mut f: F) -> ProviderBatch<T>
where
F: FnMut(&T) -> bool,
{
let filtered_items: Vec<T> = self.items.into_iter().filter(|item| f(item)).collect();
let new_count = filtered_items.len() as i64;
ProviderBatch {
items: filtered_items,
total_count: new_count,
has_next_page: self.has_next_page,
next_page_token: self.next_page_token,
}
}
}
impl<T> Default for ProviderBatch<T> {
fn default() -> Self {
Self::empty()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_new_batch() {
let batch = ProviderBatch::new(vec![1, 2, 3]);
assert_eq!(batch.len(), 3);
assert_eq!(batch.total_count, 3);
assert!(!batch.has_next_page);
assert!(batch.next_page_token.is_none());
}
#[test]
fn test_with_pagination() {
let batch = ProviderBatch::with_pagination(
vec![1, 2, 3],
100,
true,
Some("cursor-123".to_string()),
);
assert_eq!(batch.len(), 3);
assert_eq!(batch.total_count, 100);
assert!(batch.has_next_page);
assert!(!batch.is_last_page());
assert_eq!(batch.next_page_token, Some("cursor-123".to_string()));
}
#[test]
fn test_empty_batch() {
let batch: ProviderBatch<i32> = ProviderBatch::empty();
assert!(batch.is_empty());
assert_eq!(batch.len(), 0);
assert_eq!(batch.total_count, 0);
assert!(batch.is_last_page());
}
#[test]
fn test_map() {
let batch = ProviderBatch::new(vec![1, 2, 3]);
let mapped = batch.map(|x| x * 2);
assert_eq!(mapped.items, vec![2, 4, 6]);
assert_eq!(mapped.total_count, 3);
}
#[test]
fn test_filter() {
let batch = ProviderBatch::new(vec![1, 2, 3, 4, 5]);
let filtered = batch.filter(|x| x % 2 == 0);
assert_eq!(filtered.items, vec![2, 4]);
assert_eq!(filtered.total_count, 2);
}
#[test]
fn test_into_items() {
let batch = ProviderBatch::new(vec![1, 2, 3]);
let items = batch.into_items();
assert_eq!(items, vec![1, 2, 3]);
}
}