use std::collections::{BTreeMap, HashMap, HashSet};
use std::hash::Hash;
use crate::collections::{ZArray, ZOrderedRecord, ZRecord, ZSet};
use crate::modifiers::ZOptional;
use crate::primitives::{ZBoolean, ZChar, ZF32, ZInteger, ZJsonValue, ZNumber, ZString};
use crate::schema::{Schema, VldSchema};
pub trait VldType: Sized {
type Schema: Schema<Output = Self>;
fn vld_schema() -> Self::Schema;
}
macro_rules! leaf {
($($ty:ty => $schema:ty = $make:expr;)*) => {$(
impl VldType for $ty {
type Schema = $schema;
fn vld_schema() -> $schema {
$make
}
}
)*};
}
leaf! {
String => ZString = crate::string();
bool => ZBoolean = crate::boolean();
char => ZChar = crate::char();
f64 => ZNumber = crate::number();
f32 => ZF32 = crate::f32();
serde_json::Value => ZJsonValue = crate::json_value();
}
macro_rules! ints {
($($ty:ident)*) => {$(
leaf! { $ty => ZInteger<$ty> = crate::$ty(); }
)*};
}
ints!(i8 i16 i32 i64 isize u8 u16 u32 u64 usize);
impl<T: VldType> VldType for Option<T> {
type Schema = ZOptional<T::Schema>;
fn vld_schema() -> Self::Schema {
T::vld_schema().optional()
}
}
impl<T: VldType> VldType for Vec<T> {
type Schema = ZArray<T::Schema>;
fn vld_schema() -> Self::Schema {
crate::array(T::vld_schema())
}
}
impl<T: VldType + Eq + Hash> VldType for HashSet<T> {
type Schema = ZSet<T::Schema>;
fn vld_schema() -> Self::Schema {
crate::set(T::vld_schema())
}
}
impl<T: VldType> VldType for HashMap<String, T> {
type Schema = ZRecord<T::Schema>;
fn vld_schema() -> Self::Schema {
crate::record(T::vld_schema())
}
}
impl<T: VldType> VldType for BTreeMap<String, T> {
type Schema = ZOrderedRecord<T::Schema>;
fn vld_schema() -> Self::Schema {
crate::record(T::vld_schema()).ordered()
}
}