diff --git a/Cargo.toml b/Cargo.toml index 4ef55f92..ab88125e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -53,6 +53,7 @@ serde_json = "1.0.64" static_assertions = "1.1.0" tempfile = "3.2.0" thiserror = "1.0.24" +base64 = "0.13.0" # Feature optional dependencies bson = { version = "2.0.0", optional = true, features = ["chrono-0_4"] } diff --git a/src/types/connection/cursor.rs b/src/types/connection/cursor.rs index 5cafcb15..5f02eced 100644 --- a/src/types/connection/cursor.rs +++ b/src/types/connection/cursor.rs @@ -4,6 +4,8 @@ use std::{ num::{ParseFloatError, ParseIntError}, }; +use serde::{de::DeserializeOwned, Serialize}; + use crate::ID; /// Cursor type @@ -104,3 +106,23 @@ impl CursorType for f32 { self.to_string() } } + +/// A opaque cursor that encode/decode the value to base64 +pub struct OpaqueCursor(T); + +impl CursorType for OpaqueCursor +where + T: Serialize + DeserializeOwned, +{ + type Error = Box; + + fn decode_cursor(s: &str) -> Result { + let data = base64::decode_config(s, base64::URL_SAFE_NO_PAD)?; + Ok(Self(serde_json::from_slice(&data)?)) + } + + fn encode_cursor(&self) -> String { + let value = serde_json::to_vec(&self.0).unwrap_or_default(); + base64::encode_config(value, base64::URL_SAFE_NO_PAD) + } +} diff --git a/src/types/connection/mod.rs b/src/types/connection/mod.rs index 73592dd2..04cf6a82 100644 --- a/src/types/connection/mod.rs +++ b/src/types/connection/mod.rs @@ -8,7 +8,7 @@ mod page_info; use std::{fmt::Display, future::Future}; pub use connection_type::Connection; -pub use cursor::CursorType; +pub use cursor::{CursorType, OpaqueCursor}; pub use edge::Edge; pub use page_info::PageInfo;