use api_bones::cursor::Cursor;
use api_bones::pagination::KeysetPaginatedResponse;
#[cfg(feature = "hmac")]
use base64::Engine as _;
fn main() {
let payload = b"user:42:created_at:2026-01-01";
let encoded = Cursor::encode(payload);
println!("Unsigned cursor:");
println!(" encoded = {encoded}");
println!(
" url-safe = {}",
encoded
.chars()
.all(|c| c.is_alphanumeric() || c == '-' || c == '_')
);
let decoded = Cursor::decode(&encoded).unwrap();
assert_eq!(decoded, payload);
println!(" decoded = {:?}", std::str::from_utf8(&decoded).unwrap());
let err = Cursor::decode("!!!not-base64!!!").unwrap_err();
println!("\nInvalid base64 error: {err}");
#[cfg(feature = "hmac")]
{
let key = b"super-secret-signing-key";
let payload = b"user:42";
let signed = Cursor::encode_signed(payload, key);
println!("\nSigned cursor:");
println!(" encoded = {signed}");
let verified = Cursor::decode_signed(&signed, key).unwrap();
assert_eq!(verified, payload);
println!(" decoded = {:?}", std::str::from_utf8(&verified).unwrap());
let err = Cursor::decode_signed(&signed, b"wrong-key").unwrap_err();
println!(" wrong key error: {err}");
let mut raw = base64::engine::general_purpose::URL_SAFE_NO_PAD
.decode(&signed)
.unwrap();
raw[0] ^= 0xFF;
let tampered = base64::engine::general_purpose::URL_SAFE_NO_PAD.encode(&raw);
let err = Cursor::decode_signed(&tampered, key).unwrap_err();
println!(" tampered error: {err}");
}
#[cfg(not(feature = "hmac"))]
println!("\n[hmac feature not enabled — run with --features hmac to see signed cursor demo]");
let items = vec!["order-1".to_string(), "order-2".to_string()];
let next_cursor = Cursor::encode(b"order-2:created_at:2026-01-02");
let page = KeysetPaginatedResponse::first_page(items, true, Some(next_cursor.clone()));
println!("\nKeysetPaginatedResponse:");
println!(" items = {:?}", page.items);
println!(" has_next = {}", page.has_next);
println!(" has_prev = {}", page.has_prev);
println!(" next_cursor = {:?}", page.next_cursor);
assert_eq!(page.next_cursor.as_deref(), Some(next_cursor.as_str()));
}