use crate::registry::{FieldType, Kind};
use serde::{Serialize, de::DeserializeOwned};
pub use crate::schemadef::toned;
pub trait KyynType: Serialize + DeserializeOwned {
fn field_type() -> FieldType;
}
pub trait KyynKind: Serialize + DeserializeOwned {
fn kind() -> Kind;
}
impl KyynType for String {
fn field_type() -> FieldType {
FieldType::Str
}
}
impl KyynType for i64 {
fn field_type() -> FieldType {
FieldType::Int
}
}
impl KyynType for bool {
fn field_type() -> FieldType {
FieldType::Bool
}
}
impl KyynType for chrono::NaiveDate {
fn field_type() -> FieldType {
FieldType::Date
}
}
impl<T: KyynType> KyynType for Option<T> {
fn field_type() -> FieldType {
FieldType::Option(Box::new(T::field_type()))
}
}
impl<T: KyynType> KyynType for Vec<T> {
fn field_type() -> FieldType {
FieldType::List(Box::new(T::field_type()))
}
}
pub fn enum_variants<T: KyynType>() -> Vec<crate::registry::Variant> {
match T::field_type() {
FieldType::Enum(variants) => variants,
other => panic!("expected enum KyynType, got {other:?}"),
}
}
#[macro_export]
macro_rules! kyyn_schema {
(
kinds: [$($kind:ty),* $(,)?],
roles: $roles:expr,
queries: $queries:expr
$(, custom_validate: $custom:path)?
$(,)?
) => {
$crate::kyyn_schema! {
@impl
schema_hash: env!("SCHEMA_SRC_HASH"),
kinds: [$($kind),*],
roles: $roles,
queries: $queries
$(, custom_validate: $custom)?
}
};
(
#[doc(hidden)] schema_hash: $schema_hash:expr,
kinds: [$($kind:ty),* $(,)?],
roles: $roles:expr,
queries: $queries:expr
$(, custom_validate: $custom:path)?
$(,)?
) => {
$crate::kyyn_schema! {
@impl
schema_hash: $schema_hash,
kinds: [$($kind),*],
roles: $roles,
queries: $queries
$(, custom_validate: $custom)?
}
};
(
@impl
schema_hash: $schema_hash:expr,
kinds: [$($kind:ty),* $(,)?],
roles: $roles:expr,
queries: $queries:expr
$(, custom_validate: $custom:path)?
$(,)?
) => {
pub fn schema_hash() -> String {
$schema_hash.to_string()
}
pub fn registry() -> $crate::registry::Registry {
$crate::registry::Registry {
schema_hash: schema_hash(),
kinds: vec![$(<$kind as $crate::schema::KyynKind>::kind()),*],
roles: $roles,
queries: $queries,
}
}
pub fn registry_ron() -> String {
$crate::ronfmt::to_ron(®istry()).expect("registry serializes")
}
pub fn validate_entries_with(
entries: &[(String, String)],
systems: &[&str],
) -> Vec<$crate::violation::Violation> {
let mut out = $crate::validate::against_registry(®istry(), entries, systems);
$(out.extend($custom(entries, systems));)?
out
}
pub fn serve() {
$crate::protocol::serve_schema(registry, validate_entries_with);
}
};
}