#![forbid(unsafe_code)]
#![warn(missing_docs)]
pub mod error;
pub mod serde_helpers;
#[doc(hidden)]
pub use paft_utils as __utils;
#[doc(hidden)]
pub use serde as __serde;
#[doc(hidden)]
#[macro_export]
macro_rules! __string_enum_base {
(
$Type:ident, $enum_name:literal, error, {
$( $alias:literal => $variant:path ),+ $(,)?
}
) => {
impl $crate::__utils::StringCode for $Type {
fn code(&self) -> &str { $Type::code(self) }
}
impl $crate::__serde::Serialize for $Type {
fn serialize<S>(&self, serializer: S) -> ::std::result::Result<S::Ok, S::Error>
where
S: $crate::__serde::Serializer,
{
serializer.serialize_str(self.code())
}
}
impl<'de> $crate::__serde::Deserialize<'de> for $Type {
fn deserialize<D>(deserializer: D) -> ::std::result::Result<Self, D::Error>
where
D: $crate::__serde::Deserializer<'de>,
{
let raw = <String as $crate::__serde::Deserialize>::deserialize(deserializer)?;
<Self as ::std::str::FromStr>::from_str(&raw)
.map_err($crate::__serde::de::Error::custom)
}
}
impl ::std::str::FromStr for $Type {
type Err = $crate::error::PaftError;
fn from_str(input: &str) -> ::std::result::Result<Self, Self::Err> {
let trimmed = input.trim();
if trimmed.is_empty() {
return Err($crate::error::PaftError::InvalidEnumValue {
enum_name: $enum_name,
value: input.to_string(),
});
}
let token = $crate::__utils::canonicalize(trimmed);
let parsed = match token.as_ref() {
$( $alias => $variant, )*
_ => {
return Err($crate::error::PaftError::InvalidEnumValue {
enum_name: $enum_name,
value: input.to_string(),
});
}
};
Ok(parsed)
}
}
impl ::std::convert::TryFrom<String> for $Type {
type Error = $crate::error::PaftError;
fn try_from(value: String) -> ::std::result::Result<Self, Self::Error> {
<Self as ::std::str::FromStr>::from_str(&value)
}
}
impl ::std::convert::From<$Type> for String {
fn from(v: $Type) -> Self { v.code().to_string() }
}
impl $Type {
#[doc(hidden)]
pub const __ALIASES: &'static [(&'static str, $Type)] = &[
$( ($alias, $variant) ),*
];
}
};
(
$Type:ident, $enum_name:literal, other($OtherVariant:path), {
$( $alias:literal => $variant:path ),+ $(,)?
}
) => {
impl $crate::__utils::StringCode for $Type {
fn code(&self) -> &str { $Type::code(self) }
fn is_canonical(&self) -> bool { $Type::is_canonical(self) }
}
impl $Type {
#[must_use]
pub const fn is_canonical(&self) -> bool { !matches!(self, $OtherVariant(_)) }
}
impl $crate::__serde::Serialize for $Type {
fn serialize<S>(&self, serializer: S) -> ::std::result::Result<S::Ok, S::Error>
where
S: $crate::__serde::Serializer,
{
serializer.serialize_str(self.code())
}
}
impl<'de> $crate::__serde::Deserialize<'de> for $Type {
fn deserialize<D>(deserializer: D) -> ::std::result::Result<Self, D::Error>
where
D: $crate::__serde::Deserializer<'de>,
{
let raw = <String as $crate::__serde::Deserialize>::deserialize(deserializer)?;
<Self as ::std::str::FromStr>::from_str(&raw)
.map_err($crate::__serde::de::Error::custom)
}
}
impl ::std::str::FromStr for $Type {
type Err = $crate::error::PaftError;
fn from_str(input: &str) -> ::std::result::Result<Self, Self::Err> {
let trimmed = input.trim();
if trimmed.is_empty() {
return Err($crate::error::PaftError::InvalidEnumValue {
enum_name: $enum_name,
value: input.to_string(),
});
}
let token = $crate::__utils::canonicalize(trimmed);
let parsed = match token.as_ref() {
$( $alias => $variant, )*
_ => {
let canon = $crate::__utils::Canonical::try_new(trimmed)
.map_err(|_| $crate::error::PaftError::InvalidEnumValue {
enum_name: $enum_name,
value: input.to_string(),
})?;
return Ok($OtherVariant(canon));
}
};
Ok(parsed)
}
}
impl ::std::convert::TryFrom<String> for $Type {
type Error = $crate::error::PaftError;
fn try_from(value: String) -> ::std::result::Result<Self, Self::Error> {
<Self as ::std::str::FromStr>::from_str(&value)
}
}
impl ::std::convert::From<$Type> for String {
fn from(v: $Type) -> Self { v.code().to_string() }
}
impl $Type {
#[doc(hidden)]
pub const __ALIASES: &'static [(&'static str, $Type)] = &[
$( ($alias, $variant) ),*
];
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! impl_display_via_code {
( $Type:ident ) => {
impl ::std::fmt::Display for $Type {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
f.write_str(self.code())
}
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! string_enum_with_code {
(
$Type:ident, $Other:ident, $enum_name:literal,
{ $( $canon_token:literal => $canon_variant:path ),+ $(,)? },
{ $( $alias:literal => $variant:path ),* $(,)? }
) => {
impl $Type {
#[must_use]
pub fn code(&self) -> &str {
match self {
$( $canon_variant => $canon_token, )+
$Type::$Other(s) => s.as_ref(),
}
}
}
impl ::std::convert::AsRef<str> for $Type {
fn as_ref(&self) -> &str { self.code() }
}
$crate::__string_enum_base! {
$Type, $enum_name, other($Type::$Other),
{ $( $canon_token => $canon_variant ),+ $(, $alias => $variant )* }
}
};
(
$Type:ident, $Other:ident, $enum_name:literal,
{ $( $canon_token:literal => $canon_variant:path ),+ $(,)? }
) => {
$crate::string_enum_with_code!(
$Type, $Other, $enum_name,
{ $( $canon_token => $canon_variant ),+ },
{}
);
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! string_enum_closed_with_code {
(
$Type:ident, $enum_name:literal,
{ $( $canon_token:literal => $canon_variant:path ),+ $(,)? },
{ $( $alias:literal => $variant:path ),* $(,)? }
) => {
impl $Type {
#[must_use]
pub const fn code(&self) -> &str {
match self {
$( $canon_variant => $canon_token, )+
}
}
}
impl ::std::convert::AsRef<str> for $Type {
fn as_ref(&self) -> &str { self.code() }
}
$crate::__string_enum_base! {
$Type, $enum_name, error,
{ $( $canon_token => $canon_variant ),+ $(, $alias => $variant )* }
}
};
(
$Type:ident, $enum_name:literal,
{ $( $canon_token:literal => $canon_variant:path ),+ $(,)? }
) => {
$crate::string_enum_closed_with_code!(
$Type, $enum_name,
{ $( $canon_token => $canon_variant ),+ },
{}
);
};
}
pub use error::PaftError;