use crate::alphabet::{self, SIZE, SIZE_SIZE};
#[cfg(not(feature = "std"))]
use alloc::{string::String, vec::Vec};
fn divmod<const N: u32>(x: u32) -> (u32, u32) {
(x / N, x % N)
}
#[inline(always)]
fn ae(b: u8) -> u8 {
match alphabet::encode(b) {
Some(ch) => ch,
#[cfg(feature = "unsafe")]
None => unsafe { core::hint::unreachable_unchecked() },
#[cfg(not(feature = "unsafe"))]
None => unreachable!(),
}
}
fn encode_buffer(input: &[u8]) -> String {
let (input, remainder) = input.as_chunks::<2>();
let mut s = Vec::with_capacity(input.len() + input.len().div_ceil(2));
#[inline(always)]
fn core_fn([_first, _second]: [u8; 2], s: &mut Vec<u8>) {
let v = (_first as u32 * 256) + _second as u32;
let (e, rest) = divmod::<SIZE_SIZE>(v);
let (d, c) = divmod::<SIZE>(rest);
s.extend_from_slice(&[ae(c as _), ae(d as _), ae(e as _)]);
}
for c in input {
core_fn(*c, &mut s);
}
if let &[_0] = remainder {
let (d, c) = divmod::<SIZE>(_0 as u32);
s.extend_from_slice(&[ae(c as _), ae(d as _)]);
}
#[cfg(feature = "unsafe")]
unsafe {
String::from_utf8_unchecked(s)
}
#[cfg(not(feature = "unsafe"))]
String::from_utf8(s).expect("All bytes encoded must be ascii")
}
pub fn encode(input: impl AsRef<[u8]>) -> String {
encode_buffer(input.as_ref())
}
#[deprecated(
since = "3.1.0",
note = "Equivalent to `encode`. Use `encode` instead."
)]
pub fn encode_from_buffer(input: impl AsRef<[u8]>) -> String {
encode_buffer(input.as_ref())
}