1use std::collections::VecDeque;
2
3use serde::{Deserialize, Serialize};
4
5use crate::error::Error;
6
7#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
9pub struct Page<T> {
10 #[serde(rename = "data", default = "Vec::new")]
12 pub items: Vec<T>,
13 #[serde(default)]
15 pub next: Option<String>,
16}
17
18pub(crate) fn iterate<'a, T: 'a>(
23 first: Option<String>,
24 mut fetch: impl FnMut(Option<&str>) -> Result<Page<T>, Error> + 'a,
25) -> impl Iterator<Item = Result<T, Error>> + 'a {
26 let mut cursor = first.filter(|cursor| !cursor.is_empty());
27 let mut items = VecDeque::new();
28 let mut done = false;
29 std::iter::from_fn(move || loop {
30 if let Some(item) = items.pop_front() {
31 return Some(Ok(item));
32 }
33 if done {
34 return None;
35 }
36 match fetch(cursor.as_deref()) {
37 Ok(result) => {
38 items.extend(result.items);
39 match result.next.filter(|next| !next.is_empty()) {
41 Some(next) if cursor.as_deref() != Some(next.as_str()) => cursor = Some(next),
42 _ => done = true,
43 }
44 }
45 Err(error) => {
46 done = true;
47 return Some(Err(error));
48 }
49 }
50 })
51}