import base64 import binascii from datetime import datetime from fastapi import HTTPException def encode(*parts: object) -> str: raw = "|".join(str(p) for p in parts).encode() return base64.urlsafe_b64encode(raw).decode().rstrip("=") def decode(cursor: str, count: int) -> list[str]: pad = "=" * (-len(cursor) % 4) try: raw = base64.urlsafe_b64decode(cursor + pad).decode() except (binascii.Error, ValueError) as exc: raise HTTPException(status_code=400, detail="invalid cursor") from exc parts = raw.split("|", count - 1) if len(parts) != count: raise HTTPException(status_code=400, detail="invalid cursor") return parts def decode_datetime(value: str) -> datetime: try: return datetime.fromisoformat(value) except ValueError as exc: raise HTTPException(status_code=400, detail="invalid cursor") from exc