#![no_std]
#![allow(clippy::unnecessary_cast)]
#![warn(missing_docs)]
use core::fmt;
use serde::{
de::{self, Unexpected, Visitor},
Deserialize, Deserializer, Serialize, Serializer,
};
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Default)]
pub struct ConstBool<const V: bool>;
impl<const V: bool> Serialize for ConstBool<V> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_bool(V)
}
}
impl<'de, const V: bool> Deserialize<'de> for ConstBool<V> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_bool(ConstBoolVisitor::<V>)
}
}
struct ConstBoolVisitor<const V: bool>;
impl<'de, const V: bool> Visitor<'de> for ConstBoolVisitor<V> {
type Value = ConstBool<V>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "{V}")
}
fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>
where
E: de::Error,
{
if v == V {
Ok(ConstBool::<V>)
} else {
Err(E::invalid_value(Unexpected::Bool(v), &self))
}
}
}
macro_rules! declare_int {
($($type:ty => $struct:ident $visitor:ident $ser_func:ident $deser_func:ident),* $(,)?) => {
$(
#[doc = concat!("A const `", stringify!($type), "`.")]
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Default)]
pub struct $struct<const V: $type>;
impl<const V: $type> Serialize for $struct<V> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.$ser_func(V)
}
}
impl<'de, const V: $type> Deserialize<'de> for $struct<V> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
deserializer.$deser_func($visitor::<V>)
}
}
struct $visitor<const V: $type>;
impl<'de, const V: $type> Visitor<'de> for $visitor<V> {
type Value = $struct<V>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "{V}")
}
fn visit_i8<E>(self, v: i8) -> Result<Self::Value, E>
where
E: de::Error,
{
self.visit_i128(v as i128)
}
fn visit_i16<E>(self, v: i16) -> Result<Self::Value, E>
where
E: de::Error,
{
self.visit_i128(v as i128)
}
fn visit_i32<E>(self, v: i32) -> Result<Self::Value, E>
where
E: de::Error,
{
self.visit_i128(v as i128)
}
fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
where
E: de::Error,
{
self.visit_i128(v as i128)
}
fn visit_i128<E>(self, v: i128) -> Result<Self::Value, E>
where
E: de::Error,
{
if v == V as i128 {
Ok($struct::<V>)
} else {
Err(E::invalid_value(Unexpected::Signed(V as i64), &self))
}
}
fn visit_u8<E>(self, v: u8) -> Result<Self::Value, E>
where
E: de::Error,
{
self.visit_i128(v as i128)
}
fn visit_u16<E>(self, v: u16) -> Result<Self::Value, E>
where
E: de::Error,
{
self.visit_i128(v as i128)
}
fn visit_u32<E>(self, v: u32) -> Result<Self::Value, E>
where
E: de::Error,
{
self.visit_i128(v as i128)
}
fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
where
E: de::Error,
{
self.visit_i128(v as i128)
}
fn visit_u128<E>(self, v: u128) -> Result<Self::Value, E>
where
E: de::Error,
{
self.visit_i128(
i128::try_from(v)
.map_err(|_| E::invalid_value(Unexpected::Unsigned(v as u64), &Self))?,
)
}
}
)*
};
}
declare_int!(
i8 => ConstI8 ConstI8Visitor serialize_i8 deserialize_i8,
i16 => ConstI16 ConstI16Visitor serialize_i16 deserialize_i16,
i32 => ConstI32 ConstI32Visitor serialize_i32 deserialize_i32,
i64 => ConstI64 ConstI64Visitor serialize_i64 deserialize_i64,
i128 => ConstI128 ConstI128Visitor serialize_i128 deserialize_i128,
);
macro_rules! declare_uint {
($($type:ty => $struct:ident $visitor:ident $ser_func:ident $deser_func:ident),* $(,)?) => {
$(
#[doc = concat!("A const `", stringify!($type), "`.")]
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Default)]
pub struct $struct<const V: $type>;
impl<const V: $type> Serialize for $struct<V> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.$ser_func(V)
}
}
impl<'de, const V: $type> Deserialize<'de> for $struct<V> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
deserializer.$deser_func($visitor::<V>)
}
}
struct $visitor<const V: $type>;
impl<'de, const V: $type> Visitor<'de> for $visitor<V> {
type Value = $struct<V>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "{V}")
}
fn visit_i8<E>(self, v: i8) -> Result<Self::Value, E>
where
E: de::Error,
{
self.visit_i128(v as i128)
}
fn visit_i16<E>(self, v: i16) -> Result<Self::Value, E>
where
E: de::Error,
{
self.visit_i128(v as i128)
}
fn visit_i32<E>(self, v: i32) -> Result<Self::Value, E>
where
E: de::Error,
{
self.visit_i128(v as i128)
}
fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
where
E: de::Error,
{
self.visit_i128(v as i128)
}
fn visit_i128<E>(self, v: i128) -> Result<Self::Value, E>
where
E: de::Error,
{
if v < 0 {
Err(E::invalid_value(Unexpected::Signed(v as i64), &self))
} else {
self.visit_u128(v as u128)
}
}
fn visit_u8<E>(self, v: u8) -> Result<Self::Value, E>
where
E: de::Error,
{
self.visit_u128(v as u128)
}
fn visit_u16<E>(self, v: u16) -> Result<Self::Value, E>
where
E: de::Error,
{
self.visit_u128(v as u128)
}
fn visit_u32<E>(self, v: u32) -> Result<Self::Value, E>
where
E: de::Error,
{
self.visit_u128(v as u128)
}
fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
where
E: de::Error,
{
self.visit_u128(v as u128)
}
fn visit_u128<E>(self, v: u128) -> Result<Self::Value, E>
where
E: de::Error,
{
if v == V as u128 {
Ok($struct::<V>)
} else {
Err(E::invalid_value(Unexpected::Unsigned(v as u64), &self))
}
}
}
)*
};
}
declare_uint!(
u8 => ConstU8 ConstU8Visitor serialize_u8 deserialize_u8,
u16 => ConstU16 ConstU16Visitor serialize_u16 deserialize_u16,
u32 => ConstU32 ConstU32Visitor serialize_u32 deserialize_u32,
u64 => ConstU64 ConstU64Visitor serialize_u64 deserialize_u64,
u128 => ConstU128 ConstU128Visitor serialize_u128 deserialize_u128,
);
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Default)]
pub struct ConstChar<const V: char>;
impl<const V: char> Serialize for ConstChar<V> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_char(V)
}
}
impl<'de, const V: char> Deserialize<'de> for ConstChar<V> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_char(ConstCharVisitor::<V>)
}
}
struct ConstCharVisitor<const V: char>;
impl<'de, const V: char> Visitor<'de> for ConstCharVisitor<V> {
type Value = ConstChar<V>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "'{V}'")
}
fn visit_char<E>(self, v: char) -> Result<Self::Value, E>
where
E: de::Error,
{
if v == V {
Ok(ConstChar::<V>)
} else {
Err(E::invalid_value(Unexpected::Char(v), &self))
}
}
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: de::Error,
{
let mut chs = v.chars();
let ch = chs.next().ok_or_else(|| E::invalid_length(0, &self))?;
if chs.next().is_some() {
Err(E::invalid_length(2, &self))
} else {
self.visit_char(ch)
}
}
}