use std::{
hash::{Hash, Hasher},
str::FromStr,
};
#[derive(Debug)]
pub struct Category {
name: &'static str,
link: Option<&'static str>,
}
impl Category {
pub fn name(&self) -> &'static str {
self.name
}
pub fn link(&self) -> Option<&'static str> {
self.link
}
}
impl Eq for Category {}
impl PartialEq for Category {
fn eq(&self, other: &Self) -> bool {
self.name == other.name
}
}
impl Hash for Category {
fn hash<H: Hasher>(&self, state: &mut H) {
self.name.hash(state);
}
}
#[cfg(feature = "serde")]
impl serde::Serialize for &'static Category {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
self.name().serialize(serializer)
}
}
#[cfg(feature = "serde")]
struct CategoryVisitor;
#[cfg(feature = "serde")]
fn deserialize_parse<E: serde::de::Error>(code: &str) -> Result<&'static Category, E> {
code.parse().map_err(|()| {
serde::de::Error::custom(format_args!("failed to deserialize category from {code}"))
})
}
#[cfg(feature = "serde")]
impl<'de> serde::de::Visitor<'de> for CategoryVisitor {
type Value = &'static Category;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("a borrowed string")
}
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
deserialize_parse(v)
}
fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
deserialize_parse(v)
}
fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
deserialize_parse(&v)
}
}
#[cfg(feature = "serde")]
impl<'de> serde::Deserialize<'de> for &'static Category {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
deserializer.deserialize_str(CategoryVisitor)
}
}
include!(concat!(env!("OUT_DIR"), "/categories.rs"));