sui_indexer_alt_jsonrpc/
paginate.rs1use std::ops::Deref;
5
6use fastcrypto::{
7 encoding::{Base64, Encoding},
8 error::FastCryptoError,
9};
10use serde::{Serialize, de::DeserializeOwned};
11
12use crate::error::{RpcError, invalid_params};
13
14pub(crate) trait Cursor: Sized {
15 fn decode(s: &str) -> Result<Self, Error>;
18
19 fn encode(&self) -> Result<String, Error>;
22}
23
24pub(crate) struct BcsCursor<T>(pub T);
27
28pub(crate) struct JsonCursor<T>(pub T);
31
32pub(crate) struct Page<C: Cursor> {
34 pub cursor: Option<C>,
35 pub limit: i64,
36 pub descending: bool,
37}
38
39#[derive(thiserror::Error, Debug)]
40pub(crate) enum Error {
41 #[error("Failed to decode Base64: {0}")]
42 DecodingBase64(FastCryptoError),
43
44 #[error("Failed to decode BCS: {0}")]
45 DecodingBcs(bcs::Error),
46
47 #[error("Failed to decode JSON: {0}")]
48 DecodingJson(serde_json::error::Error),
49
50 #[error("Failed to encode BCS: {0}")]
51 EncodingBcs(bcs::Error),
52
53 #[error("Failed to encode JSON: {0}")]
54 EncodingJson(serde_json::error::Error),
55
56 #[error("Requested page size {requested} exceeds maximum {max}")]
57 ExceededMaxPageSize { requested: usize, max: usize },
58}
59
60impl<T: Serialize + DeserializeOwned> Cursor for BcsCursor<T> {
61 fn decode(s: &str) -> Result<Self, Error> {
62 let bytes = Base64::decode(s).map_err(Error::DecodingBase64)?;
63 let value = bcs::from_bytes(&bytes).map_err(Error::DecodingBcs)?;
64 Ok(BcsCursor(value))
65 }
66
67 fn encode(&self) -> Result<String, Error> {
68 let bytes = bcs::to_bytes(&self.0).map_err(Error::EncodingBcs)?;
69 Ok(Base64::encode(&bytes))
70 }
71}
72
73impl<T: Serialize + DeserializeOwned> Cursor for JsonCursor<T> {
74 fn decode(s: &str) -> Result<Self, Error> {
75 let bytes = Base64::decode(s).map_err(Error::DecodingBase64)?;
76 let value: T = serde_json::from_slice(&bytes).map_err(Error::DecodingJson)?;
77 Ok(JsonCursor(value))
78 }
79
80 fn encode(&self) -> Result<String, Error> {
81 let bytes = serde_json::to_vec(&self.0).map_err(Error::EncodingJson)?;
82 Ok(Base64::encode(&bytes))
83 }
84}
85
86impl<C: Cursor> Page<C> {
87 pub(crate) fn from_params<E: From<Error> + std::error::Error>(
92 default_page_size: usize,
93 max_page_size: usize,
94 cursor: Option<String>,
95 limit: Option<usize>,
96 descending: Option<bool>,
97 ) -> Result<Self, RpcError<E>> {
98 let cursor = cursor
99 .map(|c| C::decode(&c))
100 .transpose()
101 .map_err(|e| invalid_params(E::from(e)))?;
102
103 let limit = limit.unwrap_or(default_page_size);
104 if limit > max_page_size {
105 return Err(invalid_params(E::from(Error::ExceededMaxPageSize {
106 requested: limit,
107 max: max_page_size,
108 })));
109 }
110
111 Ok(Page {
112 cursor,
113 limit: limit as i64,
114 descending: descending.unwrap_or(false),
115 })
116 }
117}
118
119impl<T> Deref for BcsCursor<T> {
120 type Target = T;
121
122 fn deref(&self) -> &T {
123 &self.0
124 }
125}
126
127impl<T> Deref for JsonCursor<T> {
128 type Target = T;
129
130 fn deref(&self) -> &T {
131 &self.0
132 }
133}