#![allow(unsafe_code)]
use super::{
Base32,
encode::{GROUP, GROUP_SYMBOLS},
};
use crate::buffer::Initialized;
use std::{
fmt::{self, Alignment, Write},
mem::MaybeUninit,
};
const CHUNK: usize = 128 * GROUP;
const CHUNK_OUT: usize = 128 * GROUP_SYMBOLS;
#[derive(Debug, Clone, Copy)]
pub struct Display<'x> {
engine: Base32,
input: &'x [u8],
}
impl Base32 {
pub fn display<'x>(&self, input: &'x [u8]) -> Display<'x> {
Display {
engine: *self,
input,
}
}
}
impl fmt::Display for Display<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let len = self.engine.encoded_len(self.input.len());
let shown = f.precision().map_or(len, |precision| precision.min(len));
let padding = f.width().map_or(0, |width| width.saturating_sub(shown));
let (before, after) = match f.align() {
Some(Alignment::Right) => (padding, 0),
Some(Alignment::Center) => (padding / 2, padding - padding / 2),
Some(Alignment::Left) | None => (0, padding),
};
let fill = f.fill();
for _ in 0..before {
f.write_char(fill)?;
}
let mut buffer = [MaybeUninit::uninit(); CHUNK_OUT];
let mut left = shown;
for piece in self.input.chunks(CHUNK) {
if left == 0 {
break;
}
let written = self.engine.encode_into(piece, &mut buffer);
let text = unsafe { buffer.initialized(written.min(left)) };
debug_assert!(text.is_ascii());
f.write_str(unsafe { std::str::from_utf8_unchecked(text) })?;
left -= text.len();
}
for _ in 0..after {
f.write_char(fill)?;
}
Ok(())
}
}