atproto_oauth/
encoding.rs

1//! Base64 encoding and decoding utilities for AT Protocol OAuth.
2//!
3//! Provides traits and implementations for converting JSON serializable types to and from
4//! base64url-encoded format, commonly used in JWT headers and claims. Uses URL-safe base64
5//! encoding without padding as specified by RFC 7515 for JSON Web Signature operations.
6
7use anyhow::{Context, Result};
8use base64::{Engine as _, engine::general_purpose};
9use serde::{Deserialize, Serialize};
10use std::borrow::Cow;
11
12/// Trait for converting types to base64-encoded JSON.
13pub trait ToBase64 {
14    /// Convert the type to a base64-encoded JSON string.
15    fn to_base64(&self) -> Result<Cow<str>>;
16}
17
18impl<T: Serialize> ToBase64 for T {
19    fn to_base64(&self) -> Result<Cow<str>> {
20        let json_bytes = serde_json::to_vec(&self)?;
21        let encoded_json_bytes = general_purpose::URL_SAFE_NO_PAD.encode(json_bytes);
22        Ok(Cow::Owned(encoded_json_bytes))
23    }
24}
25
26/// Trait for converting from base64-encoded JSON to types.
27pub trait FromBase64: Sized {
28    /// Convert from a base64-encoded JSON string to the type.
29    fn from_base64<Input: ?Sized + AsRef<[u8]>>(raw: &Input) -> Result<Self>;
30}
31
32impl<T: for<'de> Deserialize<'de> + Sized> FromBase64 for T {
33    fn from_base64<Input: ?Sized + AsRef<[u8]>>(raw: &Input) -> Result<Self> {
34        let content = general_purpose::URL_SAFE_NO_PAD.decode(raw)?;
35        serde_json::from_slice(&content).context("unable to deserialize json")
36    }
37}