1use serde::{Deserialize, Serialize};
34use std::ops::{Deref, DerefMut};
35use thiserror::Error;
36
37#[derive(Debug, Clone, PartialEq)]
39pub enum Order {
40 Asc,
42 Desc,
44}
45
46#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
51pub struct Edge<N> {
52 pub cursor: Value,
54 pub node: N,
56}
57
58#[derive(Default, Debug, PartialEq, Serialize, Deserialize)]
60pub struct PageInfo {
61 pub has_previous_page: bool,
63 pub has_next_page: bool,
65 pub start_cursor: Option<Value>,
67 pub end_cursor: Option<Value>,
69}
70
71#[derive(Default, Debug, PartialEq, Serialize, Deserialize)]
75pub struct ReadResult<N> {
76 pub edges: Vec<Edge<N>>,
78 pub page_info: PageInfo,
80}
81
82impl<N> ReadResult<N> {
83 pub fn map<B, F>(self, f: F) -> ReadResult<B>
84 where
85 Self: Sized,
86 F: Fn(N) -> B,
87 {
88 ReadResult {
89 page_info: self.page_info,
90 edges: self
91 .edges
92 .into_iter()
93 .map(|e| Edge {
94 cursor: e.cursor.to_owned(),
95 node: f(e.node),
96 })
97 .collect(),
98 }
99 }
100}
101
102#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
107pub struct Value(pub String);
108
109impl Deref for Value {
110 type Target = String;
111 fn deref(&self) -> &Self::Target {
112 &self.0
113 }
114}
115
116impl From<String> for Value {
117 fn from(value: String) -> Self {
118 Self(value)
119 }
120}
121
122impl AsRef<[u8]> for Value {
123 fn as_ref(&self) -> &[u8] {
124 self.0.as_bytes()
125 }
126}
127
128pub trait Cursor {
133 type T;
135
136 fn serialize(&self) -> Self::T;
138 fn serialize_cursor(&self) -> Result<Value, CursorError>;
140 fn deserialize_cursor(value: &Value) -> Result<Self::T, CursorError>;
142}
143
144#[derive(Debug, Error)]
145pub enum CursorError {
146 #[error("base64 decode: {0}")]
147 Base64Decode(#[from] base64::DecodeError),
148
149 #[error("rkyv: {0}")]
150 Rkyv(String),
151}
152
153#[derive(Default, Serialize, Deserialize, Clone)]
170pub struct Args {
171 pub first: Option<u16>,
173 pub after: Option<Value>,
175 pub last: Option<u16>,
177 pub before: Option<Value>,
179}
180
181impl Args {
182 pub fn forward(first: u16, after: Option<Value>) -> Self {
183 Self {
184 first: Some(first),
185 after,
186 last: None,
187 before: None,
188 }
189 }
190
191 pub fn backward(last: u16, before: Option<Value>) -> Self {
192 Self {
193 first: None,
194 after: None,
195 last: Some(last),
196 before,
197 }
198 }
199
200 pub fn is_backward(&self) -> bool {
201 (self.last.is_some() || self.before.is_some())
202 && self.first.is_none()
203 && self.after.is_none()
204 }
205
206 pub fn get_info(&self) -> (u16, Option<Value>) {
207 if self.is_backward() {
208 (self.last.unwrap_or(40), self.before.clone())
209 } else {
210 (self.first.unwrap_or(40), self.after.clone())
211 }
212 }
213
214 pub fn limit(self, v: u16) -> Self {
215 if self.is_backward() {
216 Args::backward(self.last.unwrap_or(v).min(v), self.before)
217 } else {
218 Args::forward(self.first.unwrap_or(v).min(v), self.after)
219 }
220 }
221}
222
223#[derive(Debug, Error)]
224pub enum ReadError {
225 #[error("{0}")]
226 Unknown(#[from] anyhow::Error),
227
228 #[error("cursor: {0}")]
229 Cursor(#[from] CursorError),
230}
231
232pub struct Reader<T> {
250 data: Vec<T>,
251 args: Args,
252 order: Order,
253}
254
255impl<T> Reader<T>
256where
257 T: Cursor + Clone,
258 T: Send + Unpin,
259 T: Bind<T = T>,
260{
261 pub fn new(data: Vec<T>) -> Self {
262 Self {
263 data,
264 args: Args::default(),
265 order: Order::Asc,
266 }
267 }
268
269 pub fn order(&mut self, order: Order) -> &mut Self {
270 self.order = order;
271
272 self
273 }
274
275 pub fn desc(&mut self) -> &mut Self {
276 self.order(Order::Desc)
277 }
278
279 pub fn args(&mut self, args: Args) -> &mut Self {
280 self.args = args;
281
282 self
283 }
284
285 pub fn backward(&mut self, last: u16, before: Option<Value>) -> &mut Self {
286 self.args(Args {
287 last: Some(last),
288 before,
289 ..Default::default()
290 })
291 }
292
293 pub fn forward(&mut self, first: u16, after: Option<Value>) -> &mut Self {
294 self.args(Args {
295 first: Some(first),
296 after,
297 ..Default::default()
298 })
299 }
300
301 pub fn execute(&self) -> Result<ReadResult<T>, ReadError> {
302 let is_order_desc = matches!(
303 (&self.order, self.args.is_backward()),
304 (Order::Asc, true) | (Order::Desc, false)
305 );
306
307 let mut data = self.data.clone().into_iter().collect::<Vec<_>>();
308 T::sort_by(&mut data, is_order_desc);
309 let (limit, cursor) = self.args.get_info();
310
311 if let Some(cursor) = cursor.as_ref() {
312 let cursor = T::deserialize_cursor(cursor)?;
313 T::retain(&mut data, cursor, is_order_desc);
314 }
315
316 let data_len = data.len();
317 data = data.into_iter().take((limit + 1).into()).collect();
318
319 let has_more = data_len > data.len();
320 if has_more {
321 data.pop();
322 }
323
324 let mut edges = data
325 .into_iter()
326 .map(|node| Edge {
327 cursor: node
328 .serialize_cursor()
329 .expect("Error while serialize_cursor in assert_read_result"),
330 node,
331 })
332 .collect::<Vec<_>>();
333
334 if self.args.is_backward() {
335 edges = edges.into_iter().rev().collect();
336 }
337
338 let page_info = if self.args.is_backward() {
339 PageInfo {
340 has_previous_page: has_more,
341 start_cursor: edges.first().map(|e| e.cursor.to_owned()),
342 ..Default::default()
343 }
344 } else {
345 PageInfo {
346 has_next_page: has_more,
347 end_cursor: edges.last().map(|e| e.cursor.to_owned()),
348 ..Default::default()
349 }
350 };
351
352 Ok(ReadResult { edges, page_info })
353 }
354}
355
356impl<T> Deref for Reader<T> {
357 type Target = Vec<T>;
358
359 fn deref(&self) -> &Self::Target {
360 &self.data
361 }
362}
363
364impl<T> DerefMut for Reader<T> {
365 fn deref_mut(&mut self) -> &mut Self::Target {
366 &mut self.data
367 }
368}
369
370pub trait Bind {
374 type T: Cursor + Clone;
376
377 fn sort_by(data: &mut Vec<Self::T>, is_order_desc: bool);
379 fn retain(
381 data: &mut Vec<Self::T>,
382 cursor: <<Self as Bind>::T as Cursor>::T,
383 is_order_desc: bool,
384 );
385}