Skip to main content

r402_core/wire/
base64.rs

1//! Lazy base64 byte container.
2
3use std::fmt::{self, Display, Formatter};
4
5use base64::Engine;
6use base64::engine::general_purpose::STANDARD as B64;
7
8/// Raw bytes holding the base64-encoded ASCII representation of some payload.
9///
10/// Useful as a field type for x402 wire messages that transport arbitrary
11/// binary data (for example, the raw Solana transaction wrapped in
12/// [`PaymentPayload`](super::PaymentPayload)). Encoding is eager, decoding
13/// is deferred.
14///
15/// # Examples
16///
17/// ```
18/// use r402_core::wire::Base64Bytes;
19///
20/// let encoded = Base64Bytes::encode(b"hello world");
21/// let decoded = encoded.decode().unwrap();
22/// assert_eq!(decoded, b"hello world");
23/// ```
24#[derive(Debug, Clone, PartialEq, Eq)]
25pub struct Base64Bytes(pub Vec<u8>);
26
27impl Base64Bytes {
28    /// Decodes the inner base64 bytes into their raw binary form.
29    ///
30    /// # Errors
31    ///
32    /// Returns a [`base64::DecodeError`] when the stored bytes are not
33    /// valid base64.
34    pub fn decode(&self) -> Result<Vec<u8>, base64::DecodeError> {
35        B64.decode(&self.0)
36    }
37
38    /// Encodes arbitrary bytes into a [`Base64Bytes`] wrapper.
39    #[must_use]
40    pub fn encode<T: AsRef<[u8]>>(input: T) -> Self {
41        Self(B64.encode(input.as_ref()).into_bytes())
42    }
43}
44
45impl AsRef<[u8]> for Base64Bytes {
46    fn as_ref(&self) -> &[u8] {
47        &self.0
48    }
49}
50
51impl From<&[u8]> for Base64Bytes {
52    fn from(slice: &[u8]) -> Self {
53        Self(slice.to_vec())
54    }
55}
56
57impl Display for Base64Bytes {
58    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
59        f.write_str(&String::from_utf8_lossy(&self.0))
60    }
61}