#[doc(hidden)]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum Formatting {
Debug,
Display,
}
impl Formatting {
#[inline(always)]
pub const fn is_display(self) -> bool {
matches!(self, Formatting::Display)
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum NumberFormatting {
Decimal,
Hexadecimal,
Binary,
}
#[doc(hidden)]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(u8)]
pub enum HexFormatting {
Upper = b'A' - 10,
Lower = b'a' - 10,
}
impl NumberFormatting {
#[cfg(test)]
#[cfg(feature = "fmt")]
pub(crate) const ALL: &'static [Self; 3] = &[
NumberFormatting::Decimal,
NumberFormatting::Hexadecimal,
NumberFormatting::Binary,
];
}
#[must_use]
#[derive(Debug, Copy, Clone)]
pub struct FormattingFlags {
num_fmt: NumberFormatting,
hex_fmt: HexFormatting,
is_alternate: bool,
}
#[doc(hidden)]
impl FormattingFlags {
pub const __REG: Self = Self::NEW.set_alternate(false).set_decimal();
pub const __HEX: Self = Self::NEW.set_alternate(false).set_hexadecimal();
pub const __LOWHEX: Self = Self::NEW.set_alternate(false).set_lower_hexadecimal();
pub const __BIN: Self = Self::NEW.set_alternate(false).set_binary();
pub const __A_REG: Self = Self::NEW.set_alternate(true).set_decimal();
pub const __A_HEX: Self = Self::NEW.set_alternate(true).set_hexadecimal();
pub const __A_LOWHEX: Self = Self::NEW.set_alternate(true).set_lower_hexadecimal();
pub const __A_BIN: Self = Self::NEW.set_alternate(true).set_binary();
}
impl FormattingFlags {
#[doc(hidden)]
pub const DEFAULT: Self = Self {
num_fmt: NumberFormatting::Decimal,
hex_fmt: HexFormatting::Upper,
is_alternate: false,
};
pub const NEW: Self = Self {
num_fmt: NumberFormatting::Decimal,
hex_fmt: HexFormatting::Upper,
is_alternate: false,
};
#[inline]
pub const fn new() -> Self {
Self::NEW
}
#[inline]
pub const fn set_num_fmt(mut self, num_fmt: NumberFormatting) -> Self {
self.num_fmt = num_fmt;
self
}
#[inline]
pub const fn set_decimal(mut self) -> Self {
self.num_fmt = NumberFormatting::Decimal;
self
}
#[inline]
pub const fn set_hexadecimal(mut self) -> Self {
self.num_fmt = NumberFormatting::Hexadecimal;
self.hex_fmt = HexFormatting::Upper;
self
}
#[inline]
pub const fn set_lower_hexadecimal(mut self) -> Self {
self.num_fmt = NumberFormatting::Hexadecimal;
self.hex_fmt = HexFormatting::Lower;
self
}
#[inline]
pub const fn set_binary(mut self) -> Self {
self.num_fmt = NumberFormatting::Binary;
self
}
#[inline]
pub const fn set_alternate(mut self, is_alternate: bool) -> Self {
self.is_alternate = is_alternate;
self
}
#[inline]
pub const fn num_fmt(self) -> NumberFormatting {
self.num_fmt
}
#[inline]
pub const fn is_alternate(self) -> bool {
self.is_alternate
}
pub(crate) const fn hex_fmt(self) -> HexFormatting {
self.hex_fmt
}
}
#[doc(hidden)]
pub struct LenAndArray<T: ?Sized> {
pub len: usize,
pub array: T,
}
#[doc(hidden)]
pub struct StartAndArray<T: ?Sized> {
pub start: usize,
pub array: T,
}
#[doc(hidden)]
pub struct ForEscaping {
pub is_escaped: u128,
pub is_backslash_escaped: u128,
pub escape_char: [u8; 16],
}
impl ForEscaping {
#[inline(always)]
pub const fn get_backslash_escape(b: u8) -> u8 {
FOR_ESCAPING.escape_char[(b & 0b1111) as usize]
}
}
#[doc(hidden)]
#[inline(always)]
pub const fn hex_as_ascii(n: u8, hex_fmt: HexFormatting) -> u8 {
if n < 10 {
n + b'0'
} else {
n + (hex_fmt as u8)
}
}
#[doc(hidden)]
#[allow(clippy::no_effect)]
pub const FOR_ESCAPING: &ForEscaping = {
let mut is_backslash_escaped = 0;
let escaped = [
(b'\t', b't'),
(b'\n', b'n'),
(b'\r', b'r'),
(b'\'', b'\''),
(b'"', b'"'),
(b'\\', b'\\'),
];
let mut escape_char = [0u8; 16];
__for_range! {i in 0..escaped.len() =>
let (code, escape) = escaped[i];
is_backslash_escaped |= 1 << code;
let ei = (code & 0b1111) as usize;
let prev_escape = escape_char[ei] as usize;
["Oh no, some escaped character uses the same 4 lower bits as another"][prev_escape];
escape_char[ei] = escape;
}
let is_escaped = is_backslash_escaped | 0xFFFF_FFFF;
&ForEscaping {
escape_char,
is_backslash_escaped,
is_escaped,
}
};