use crate::error::ParseError;
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(u8)]
pub enum Category {
Success = b'S',
Warning = b'W',
NoData = b'N',
Exception = b'X',
}
impl From<Category> for char {
#[inline]
fn from(c: Category) -> Self {
c as u8 as char
}
}
impl From<Category> for u8 {
#[inline]
fn from(c: Category) -> Self {
c as u8
}
}
impl TryFrom<char> for Category {
type Error = crate::error::ParseError;
#[inline]
fn try_from(char: char) -> Result<Self, Self::Error> {
Ok(match char {
'S' => Category::Success,
'W' => Category::Warning,
'N' => Category::NoData,
'X' => Category::Exception,
_ => {
return Err(ParseError::InvalidChar {
byte: {
let mut buf = [0; 4];
char.encode_utf8(&mut buf);
buf[0]
},
position: 0,
})
}
})
}
}
impl TryFrom<u8> for Category {
type Error = crate::error::ParseError;
#[inline]
fn try_from(byte: u8) -> Result<Self, Self::Error> {
Ok(match byte {
b'S' => Category::Success,
b'W' => Category::Warning,
b'N' => Category::NoData,
b'X' => Category::Exception,
_ => return Err(ParseError::InvalidChar { byte, position: 0 }),
})
}
}
#[cfg(feature = "serde")]
mod _serde {
use super::Category;
use core::fmt;
use serde::de::{self, Unexpected, Visitor};
struct CatVisitor;
impl<'de> Visitor<'de> for CatVisitor {
type Value = Category;
fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "one of 'S', 'W', 'N' or 'X'")
}
fn visit_str<E: de::Error>(self, value: &str) -> Result<Self::Value, E> {
if value.len() == 1 {
self.visit_char(value.chars().next().unwrap())
} else {
Err(E::invalid_length(value.len(), &self))
}
}
fn visit_u8<E: de::Error>(self, value: u8) -> Result<Self::Value, E> {
value
.try_into()
.map_err(|_| E::invalid_value(Unexpected::Unsigned(value.into()), &self))
}
fn visit_char<E: de::Error>(self, value: char) -> Result<Self::Value, E> {
value
.try_into()
.map_err(|_| E::invalid_value(Unexpected::Char(value), &self))
}
}
impl serde::Serialize for Category {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_char(char::from(*self))
}
}
}
const _: () = assert!(core::mem::size_of::<Category>() == 1);
const _: () = assert!(core::mem::size_of::<Option<Category>>() == 1);
const _: () = assert!(core::mem::size_of::<Option<Option<Category>>>() == 1);