eureka_mmanager_core/data_pulls/
results.rs1use std::num::TryFromIntError;
2
3use mangadex_api_schema_rust::v5::Results;
4use mangadex_api_types_rust::{ResponseType, ResultType};
5use serde::{Deserialize, Serialize};
6#[cfg(feature = "stream")]
7use tokio_stream::{Stream, StreamExt};
8
9#[derive(Debug, Serialize, Deserialize, Clone)]
11pub struct Collection<T> {
12 pub data: Vec<T>,
13 pub offset: usize,
14 pub limit: usize,
15 pub total: usize,
16}
17
18impl<T> Collection<T> {
19 pub fn into_results(self) -> Result<Results<T>, TryFromIntError> {
25 self.try_into()
26 }
27}
28
29impl<T> TryFrom<Collection<T>> for Results<T> {
30 type Error = TryFromIntError;
31 fn try_from(value: Collection<T>) -> Result<Self, Self::Error> {
32 Ok(Self {
33 result: ResultType::Ok,
34 response: ResponseType::Collection,
35 data: value.data,
36 limit: value.limit.try_into()?,
37 offset: value.offset.try_into()?,
38 total: value.total.try_into()?,
39 })
40 }
41}
42
43pub trait AsyncPaginate<T> {
51 fn paginate(
52 self,
53 offset: usize,
54 limit: usize,
55 ) -> impl std::future::Future<Output = Collection<T>> + Send;
56}
57
58pub trait Paginate<T> {
64 fn paginate(self, offset: usize, limit: usize) -> Collection<T>;
65}
66
67impl<T> Paginate<T> for Vec<T> {
68 fn paginate(self, offset: usize, limit: usize) -> Collection<T> {
69 let total = self.len();
70 let data = self
71 .into_iter()
72 .skip(offset)
73 .take(limit)
74 .collect::<Vec<_>>();
75 Collection {
76 total,
77 data,
78 offset,
79 limit,
80 }
81 }
82}
83
84#[cfg(feature = "stream")]
85#[cfg_attr(docsrs, doc(cfg(feature = "stream")))]
86impl<S, T> AsyncPaginate<T> for S
87where
88 S: Stream<Item = T> + Send,
89 T: Send,
90{
91 async fn paginate(self, offset: usize, limit: usize) -> Collection<T> {
92 let stream = Box::pin(self);
93 let (_, pre_total) = stream.size_hint();
94 if let Some(total) = pre_total {
95 let data = stream.skip(offset).take(limit).collect::<Vec<_>>().await;
96 Collection {
97 data,
98 offset,
99 limit,
100 total,
101 }
102 } else {
103 stream.collect::<Vec<_>>().await.paginate(offset, limit)
104 }
105 }
106}