use std::fmt;
use palpo_macros::DisplayAsRefStr;
use salvo::oapi::ToSchema;
use serde::{
Deserialize, Deserializer, Serialize,
de::{self, Visitor},
};
use crate::{IdParseError, PrivOwnedStr};
#[derive(ToSchema, Clone, Debug, PartialEq, Eq, Hash, DisplayAsRefStr)]
pub enum VoipVersionId {
V0,
V1,
#[doc(hidden)]
#[salvo(schema(skip))]
_Custom(PrivOwnedStr),
}
impl VoipVersionId {
pub fn as_str(&self) -> &str {
match &self {
Self::V0 => "0",
Self::V1 => "1",
Self::_Custom(PrivOwnedStr(s)) => s,
}
}
pub fn as_bytes(&self) -> &[u8] {
self.as_str().as_bytes()
}
}
impl From<VoipVersionId> for String {
fn from(id: VoipVersionId) -> Self {
match id {
VoipVersionId::_Custom(PrivOwnedStr(version)) => version.into(),
_ => id.as_str().to_owned(),
}
}
}
impl AsRef<str> for VoipVersionId {
fn as_ref(&self) -> &str {
self.as_str()
}
}
impl<'de> Deserialize<'de> for VoipVersionId {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct CallVersionVisitor;
impl<'de> Visitor<'de> for CallVersionVisitor {
type Value = VoipVersionId;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("0 or string")
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(value.into())
}
fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
where
E: de::Error,
{
let uint = u64::try_from(value).map_err(de::Error::custom)?;
Self::Value::try_from(uint).map_err(de::Error::custom)
}
}
deserializer.deserialize_any(CallVersionVisitor)
}
}
impl Serialize for VoipVersionId {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
match self {
Self::V0 => serializer.serialize_u64(0),
_ => serializer.serialize_str(self.as_str()),
}
}
}
impl TryFrom<u64> for VoipVersionId {
type Error = IdParseError;
fn try_from(u: u64) -> Result<Self, Self::Error> {
palpo_identifiers_validation::voip_version_id::validate(u)?;
Ok(Self::V0)
}
}
fn from<T>(s: T) -> VoipVersionId
where
T: AsRef<str> + Into<Box<str>>,
{
match s.as_ref() {
"1" => VoipVersionId::V1,
_ => VoipVersionId::_Custom(PrivOwnedStr(s.into())),
}
}
impl From<&str> for VoipVersionId {
fn from(s: &str) -> Self {
from(s)
}
}
impl From<String> for VoipVersionId {
fn from(s: String) -> Self {
from(s)
}
}