use crate::page::Page; use serde::Deserialize; /// Abstracts away the `next_page` logic into a single stream of items #[derive(Debug, Clone)] pub struct ItemsIter<'a, T: Clone + for<'de> Deserialize<'de>> { page: Page<'a, T>, buffer: Vec, cur_idx: usize, cur_page: usize, use_initial: bool, } impl<'a, T: Clone + for<'de> Deserialize<'de>> ItemsIter<'a, T> { pub(crate) fn new(page: Page<'a, T>) -> ItemsIter<'a, T> { ItemsIter { page, buffer: vec![], cur_idx: 0, cur_page: 0, use_initial: true, } } fn need_next_page(&self) -> bool { self.buffer.is_empty() || self.cur_idx == self.buffer.len() } async fn fill_next_page(&mut self) -> Option<()> { let items = if let Ok(items) = self.page.next_page().await { items } else { return None; }; if let Some(items) = items { if items.is_empty() { return None; } self.buffer = items; self.cur_idx = 0; self.cur_page += 1; Some(()) } else { None } } pub fn page_num(&self) -> usize { self.cur_page } pub async fn next_item(&mut self) -> Option { if self.use_initial { if self.page.initial_items.is_empty() || self.cur_idx == self.page.initial_items.len() { return None; } let idx = self.cur_idx; if self.cur_idx == self.page.initial_items.len() - 1 { self.cur_idx = 0; self.use_initial = false; } else { self.cur_idx += 1; } Some(self.page.initial_items[idx].clone()) } else { if self.need_next_page() && self.fill_next_page().await.is_none() { return None; } let idx = self.cur_idx; self.cur_idx += 1; Some(self.buffer[idx].clone()) } } }