use core::slice;
use crate::display::InputDisplay;
use crate::fmt;
use crate::input::{Bound, Bytes, Input};
use crate::util::utf8::CharBytes;
#[derive(Copy, Clone)]
#[must_use]
pub struct Value<'i>(ValueInner<'i>);
#[derive(Copy, Clone)]
enum ValueInner<'i> {
Byte(u8),
Char(CharBytes),
Bytes(&'i [u8]),
String(&'i str),
}
impl<'i> Value<'i> {
#[must_use]
pub fn as_bytes(&self) -> &[u8] {
match &self.0 {
ValueInner::Byte(v) => slice::from_ref(v),
ValueInner::Char(v) => v.as_bytes(),
ValueInner::Bytes(v) => v,
ValueInner::String(v) => v.as_bytes(),
}
}
pub fn display(&self) -> InputDisplay<'_> {
let display = Bytes::new(self.as_bytes(), Bound::StartEnd).display();
match self.0 {
ValueInner::Byte(_) | ValueInner::Bytes(_) => display,
ValueInner::Char(_) | ValueInner::String(_) => display.str_hint(),
}
}
}
impl<'i> fmt::Debug for Value<'i> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let name = match self.0 {
ValueInner::Byte(_) => "Byte",
ValueInner::Char(_) => "Char",
ValueInner::Bytes(_) => "Bytes",
ValueInner::String(_) => "String",
};
let display = self.display().with_formatter(f);
f.debug_tuple(name).field(&display).finish()
}
}
impl<'i> From<u8> for Value<'i> {
fn from(v: u8) -> Self {
Self(ValueInner::Byte(v))
}
}
impl<'i> From<char> for Value<'i> {
fn from(v: char) -> Self {
Self(ValueInner::Char(v.into()))
}
}
impl<'i> From<&'i [u8]> for Value<'i> {
#[inline(always)]
fn from(v: &'i [u8]) -> Self {
Self(ValueInner::Bytes(v))
}
}
impl<'i> From<&'i str> for Value<'i> {
#[inline(always)]
fn from(v: &'i str) -> Self {
Self(ValueInner::String(v))
}
}
impl<'i, const N: usize> From<&'i [u8; N]> for Value<'i> {
#[inline(always)]
fn from(v: &'i [u8; N]) -> Self {
Self(ValueInner::Bytes(v))
}
}