use super::*;
pub(super) fn decode_cursor(cursor: &str) -> Result<usize> {
let bytes = BASE64
.decode(cursor)
.map_err(|_| Error::JsonRpc(JsonRpcError::invalid_params("Invalid pagination cursor")))?;
let s = String::from_utf8(bytes)
.map_err(|_| Error::JsonRpc(JsonRpcError::invalid_params("Invalid pagination cursor")))?;
s.parse::<usize>()
.map_err(|_| Error::JsonRpc(JsonRpcError::invalid_params("Invalid pagination cursor")))
}
pub(super) fn encode_cursor(offset: usize) -> String {
BASE64.encode(offset.to_string())
}
pub(super) fn paginate<T>(
items: Vec<T>,
cursor: Option<&str>,
page_size: Option<usize>,
) -> Result<(Vec<T>, Option<String>)> {
let Some(page_size) = page_size else {
return Ok((items, None));
};
let offset = match cursor {
Some(c) => decode_cursor(c)?,
None => 0,
};
if offset >= items.len() {
return Ok((Vec::new(), None));
}
let end = (offset + page_size).min(items.len());
let next_cursor = if end < items.len() {
Some(encode_cursor(end))
} else {
None
};
let mut items = items;
let page = items.drain(offset..end).collect();
Ok((page, next_cursor))
}