use core::fmt;
use core::marker::PhantomData;
use ::serde::de::{Error, Visitor};
pub use ::serde::{Deserialize, Deserializer, Serialize, Serializer};
use crate::encoding::{DecodeIdError, EncodedId};
use crate::id::{self, Id, ParseIdError};
pub fn serialize<I: Id, S: Serializer>(id: &I, serializer: S) -> Result<S::Ok, S::Error> {
serializer.collect_str(&id.get())
}
pub fn deserialize<'de, I: Id, D: Deserializer<'de>>(deserializer: D) -> Result<I, D::Error> {
if deserializer.is_human_readable() {
deserializer.deserialize_any(IdVisitor(PhantomData))
} else {
deserializer.deserialize_str(IdVisitor(PhantomData))
}
}
struct IdVisitor<I>(PhantomData<I>);
impl<I: Id> Visitor<'_> for IdVisitor<I> {
type Value = I;
fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("an ID as a decimal string or an integer")
}
fn visit_str<E: Error>(self, value: &str) -> Result<I, E> {
id::parse(value).map_err(|error| match error {
ParseIdError::Int(error) => E::custom(error),
ParseIdError::Invalid(error) => E::custom(error),
})
}
fn visit_u64<E: Error>(self, value: u64) -> Result<I, E> {
id::from_u64(value).map_err(E::custom)
}
fn visit_i64<E: Error>(self, value: i64) -> Result<I, E> {
id::from_i64(value).map_err(E::custom)
}
}
pub fn serialize_encoded<I: EncodedId, S: Serializer>(
id: &I,
serializer: S,
) -> Result<S::Ok, S::Error> {
serializer.serialize_str(id.encode().as_str())
}
pub fn deserialize_encoded<'de, I: EncodedId, D: Deserializer<'de>>(
deserializer: D,
) -> Result<I, D::Error> {
deserializer.deserialize_str(EncodedVisitor(PhantomData))
}
struct EncodedVisitor<I>(PhantomData<I>);
impl<I: EncodedId> Visitor<'_> for EncodedVisitor<I> {
type Value = I;
fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("an ID encoded in its alphabet")
}
fn visit_str<E: Error>(self, value: &str) -> Result<I, E> {
I::decode(value).map_err(|error| match error {
DecodeIdError::Invalid(error) => E::custom(error),
error => E::custom(error),
})
}
}