use serde::de::{Error as _, Unexpected};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
macro_rules! schema_tag {
($(#[$meta:meta])* $name:ident, $value:path) => {
$(#[$meta])*
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Default)]
pub struct $name;
impl $name {
#[must_use]
pub fn as_str(&self) -> &'static str {
$value
}
}
impl Serialize for $name {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
serializer.serialize_str($value)
}
}
impl<'de> Deserialize<'de> for $name {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let text = String::deserialize(deserializer)?;
if text == $value {
Ok(Self)
} else {
Err(D::Error::invalid_value(
Unexpected::Str(&text),
&$value,
))
}
}
}
impl std::fmt::Display for $name {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str($value)
}
}
#[cfg(feature = "schema")]
impl schemars::JsonSchema for $name {
fn schema_name() -> String {
stringify!($name).to_string()
}
fn json_schema(_: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
let mut schema = schemars::schema::SchemaObject {
instance_type: Some(schemars::schema::InstanceType::String.into()),
..Default::default()
};
schema.const_value = Some(serde_json::Value::String($value.to_string()));
schema.into()
}
}
};
}
schema_tag!(
DefinitionTag,
crate::definition::DEFINITION_SCHEMA_V1
);
schema_tag!(
InstanceTag,
crate::instance::INSTANCE_SCHEMA_V1
);
schema_tag!(
ResponseTag,
crate::response::RESPONSE_SCHEMA_V1
);
#[cfg(feature = "schema")]
#[macro_export]
macro_rules! string_scalar_schema {
($name:ident, $pattern:expr) => {
impl schemars::JsonSchema for $name {
fn schema_name() -> String {
stringify!($name).to_string()
}
fn json_schema(_: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
let mut schema = schemars::schema::SchemaObject {
instance_type: Some(schemars::schema::InstanceType::String.into()),
..Default::default()
};
schema.string().min_length = Some(1);
if let Some(pattern) = $pattern {
schema.string().pattern = Some(pattern.to_string());
}
schema.into()
}
}
};
}