use core::{fmt, ops::Deref, str};
use std::ops::DerefMut;
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct NStr<const N: usize>([u8; N]);
#[doc(hidden)]
pub const fn __nstr<const N: usize>(s: &str) -> NStr<N> {
if N != s.len() {
panic!("string does not match claimed length");
};
let src = s.as_bytes();
let mut dst = [0; N];
let mut i = 0;
while i < N {
dst[i] = src[i];
i += 1;
}
NStr(dst)
}
#[macro_export]
macro_rules! nstr {
($lit:literal) => {
$crate::nstr::__nstr::<{ $lit.len() }>($lit).into()
};
}
impl<const N: usize> Deref for NStr<N> {
type Target = str;
#[inline]
fn deref(&self) -> &Self::Target {
unsafe { str::from_utf8_unchecked(&self.0) }
}
}
impl<const N: usize> DerefMut for NStr<N> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { str::from_utf8_unchecked_mut(&mut self.0) }
}
}
impl<const N: usize> fmt::Debug for NStr<N> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.deref())
}
}
impl<const N: usize> fmt::Display for NStr<N> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.deref())
}
}