2020-05-28 00:02:00 +00:00
|
|
|
use crate::ID;
|
|
|
|
use byteorder::{ReadBytesExt, BE};
|
|
|
|
use std::convert::Infallible;
|
|
|
|
use std::fmt::Display;
|
2020-05-05 05:21:45 +00:00
|
|
|
|
2020-05-28 00:02:00 +00:00
|
|
|
/// Cursor type
|
2020-05-05 05:21:45 +00:00
|
|
|
///
|
|
|
|
/// A custom scalar that serializes as a string.
|
|
|
|
/// https://relay.dev/graphql/connections.htm#sec-Cursor
|
2020-05-28 00:02:00 +00:00
|
|
|
pub trait CursorType: Sized {
|
|
|
|
/// Error type for `encode_cursor` and `decode_cursor`.
|
|
|
|
type Error: Display;
|
2020-05-05 05:21:45 +00:00
|
|
|
|
2020-05-28 00:02:00 +00:00
|
|
|
/// Decode cursor from string.
|
|
|
|
fn decode_cursor(s: &str) -> Result<Self, Self::Error>;
|
2020-05-05 05:21:45 +00:00
|
|
|
|
2020-05-28 00:02:00 +00:00
|
|
|
/// Encode cursor to string.
|
|
|
|
fn encode_cursor(&self) -> Result<String, Self::Error>;
|
2020-05-05 05:21:45 +00:00
|
|
|
}
|
|
|
|
|
2020-05-28 00:02:00 +00:00
|
|
|
impl CursorType for usize {
|
|
|
|
type Error = anyhow::Error;
|
|
|
|
|
|
|
|
fn decode_cursor(s: &str) -> Result<Self, Self::Error> {
|
|
|
|
let data = base64::decode(s)?;
|
|
|
|
Ok(data.as_slice().read_u32::<BE>()? as usize)
|
2020-05-05 05:21:45 +00:00
|
|
|
}
|
|
|
|
|
2020-05-28 00:02:00 +00:00
|
|
|
fn encode_cursor(&self) -> Result<String, Self::Error> {
|
|
|
|
Ok(base64::encode((*self as u32).to_be_bytes()))
|
2020-05-10 10:38:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-28 00:02:00 +00:00
|
|
|
impl CursorType for String {
|
|
|
|
type Error = Infallible;
|
|
|
|
|
|
|
|
fn decode_cursor(s: &str) -> Result<Self, Self::Error> {
|
|
|
|
Ok(s.to_string())
|
2020-05-10 14:25:16 +00:00
|
|
|
}
|
|
|
|
|
2020-05-28 00:02:00 +00:00
|
|
|
fn encode_cursor(&self) -> Result<String, Self::Error> {
|
|
|
|
Ok(self.clone())
|
2020-05-10 10:27:46 +00:00
|
|
|
}
|
2020-05-28 00:02:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl CursorType for ID {
|
|
|
|
type Error = Infallible;
|
2020-05-10 10:27:46 +00:00
|
|
|
|
2020-05-28 00:02:00 +00:00
|
|
|
fn decode_cursor(s: &str) -> Result<Self, Self::Error> {
|
|
|
|
Ok(s.to_string().into())
|
2020-05-05 05:21:45 +00:00
|
|
|
}
|
|
|
|
|
2020-05-28 00:02:00 +00:00
|
|
|
fn encode_cursor(&self) -> Result<String, Self::Error> {
|
|
|
|
Ok(self.to_string())
|
2020-05-05 05:21:45 +00:00
|
|
|
}
|
|
|
|
}
|