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