use crate::alphabet::Config;
use crate::scalar::encode_scalar;
use core::fmt;
#[derive(Debug, Clone, Copy)]
pub struct Base64Display<'a> {
data: &'a [u8],
config: &'static Config,
}
impl<'a> Base64Display<'a> {
#[inline(always)]
pub const fn new(data: &'a [u8], config: &'static Config) -> Self {
Self { data, config }
}
#[inline(always)]
pub const fn standard(data: &'a [u8]) -> Self {
Self {
data,
config: &Config::STANDARD,
}
}
#[inline(always)]
pub const fn url_safe(data: &'a [u8]) -> Self {
Self {
data,
config: &Config::URL_SAFE_NO_PAD,
}
}
}
impl<'a> fmt::Display for Base64Display<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut buf = [0u8; 64];
let chunks = self.data.chunks(48);
for chunk in chunks {
let written = encode_scalar(chunk, &mut buf, self.config);
let s = unsafe { core::str::from_utf8_unchecked(&buf[..written]) };
f.write_str(s)?;
}
Ok(())
}
}
#[inline(always)]
pub fn display<'a>(data: &'a [u8]) -> Base64Display<'a> {
Base64Display::standard(data)
}
#[inline(always)]
pub fn display_config<'a>(data: &'a [u8], config: &'static Config) -> Base64Display<'a> {
Base64Display::new(data, config)
}
#[inline(always)]
pub fn display_url_safe<'a>(data: &'a [u8]) -> Base64Display<'a> {
Base64Display::url_safe(data)
}
#[cfg(all(test, feature = "alloc"))]
mod tests {
use super::*;
#[cfg(feature = "alloc")]
#[test]
fn test_display_formatting() {
extern crate alloc;
use alloc::format;
let data = b"Hello Rust 2026";
let formatted = format!("{}", display(data));
assert_eq!(formatted, "SGVsbG8gUnVzdCAyMDI2");
let formatted_url = format!("{}", display_url_safe(data));
assert_eq!(formatted_url, "SGVsbG8gUnVzdCAyMDI2");
}
}