use std::borrow::Cow;
use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList, VecDeque};
use std::hash::{BuildHasher, Hash};
use std::marker::PhantomData;
use serde::ser::Serialize;
#[cfg(feature = "bytes")]
use serde_bytes::{ByteBuf, Bytes};
use types::*;
use Schema;
pub trait SchemaSerialize: Serialize {
fn schema_register<S: Schema>(schema: &mut S) -> Result<S::TypeId, S::Error>;
}
macro_rules! primitive_impl {
($t:ty, $id:tt) => {
impl SchemaSerialize for $t {
#[inline]
fn schema_register<S: Schema>(_: &mut S) -> Result<S::TypeId, S::Error> {
Ok(TypeId::$id)
}
}
};
}
primitive_impl!(bool, BOOL);
primitive_impl!(i8, I8);
primitive_impl!(i16, I16);
primitive_impl!(i32, I32);
primitive_impl!(i64, I64);
primitive_impl!(isize, I64);
primitive_impl!(u8, U8);
primitive_impl!(u16, U16);
primitive_impl!(u32, U32);
primitive_impl!(u64, U64);
primitive_impl!(usize, U64);
primitive_impl!(f32, F32);
primitive_impl!(f64, F64);
primitive_impl!(char, CHAR);
impl SchemaSerialize for str {
#[inline]
fn schema_register<S: Schema>(_: &mut S) -> Result<S::TypeId, S::Error> {
Ok(TypeId::STR)
}
}
impl SchemaSerialize for String {
#[inline]
fn schema_register<S: Schema>(_: &mut S) -> Result<S::TypeId, S::Error> {
Ok(TypeId::STR)
}
}
#[cfg(feature = "bytes")]
impl<'a> SchemaSerialize for Bytes<'a> {
#[inline]
fn schema_register<S: Schema>(_: &mut S) -> Result<S::TypeId, S::Error> {
Ok(TypeId::BYTES)
}
}
#[cfg(feature = "bytes")]
impl SchemaSerialize for ByteBuf {
#[inline]
fn schema_register<S: Schema>(_: &mut S) -> Result<S::TypeId, S::Error> {
Ok(TypeId::BYTES)
}
}
impl<T: SchemaSerialize> SchemaSerialize for Option<T> {
#[inline]
fn schema_register<S: Schema>(schema: &mut S) -> Result<S::TypeId, S::Error> {
let id = T::schema_register(schema)?;
schema.register_type(Type::Option(OptionType { value: id }))
}
}
impl<T> SchemaSerialize for PhantomData<T> {
#[inline]
fn schema_register<S: Schema>(schema: &mut S) -> Result<S::TypeId, S::Error> {
schema.register_type(Type::UnitStruct(UnitStructType {
_phan: PhantomData,
name: Cow::Borrowed("PhantomData"),
}))
}
}
macro_rules! array_impls {
{$($len:tt)+} => {
$(
impl<T: SchemaSerialize> SchemaSerialize for [T; $len] {
#[inline]
fn schema_register<S: Schema>(schema: &mut S) -> Result<S::TypeId, S::Error> {
let id = T::schema_register(schema)?;
schema.register_type(Type::Seq(SeqType { len: Some($len), element: id }))
}
}
)+
}
}
array_impls! {
00 01 02 03 04 05 06 07 08 09
10 11 12 13 14 15 16 17 18 19
20 21 22 23 24 25 26 27 28 29
30 31 32
}
impl<T: SchemaSerialize> SchemaSerialize for [T] {
#[inline]
fn schema_register<S: Schema>(schema: &mut S) -> Result<S::TypeId, S::Error> {
let id = T::schema_register(schema)?;
schema.register_type(Type::Seq(SeqType {
len: None,
element: id,
}))
}
}
macro_rules! seq_impl {
($ty:ident <
T $(: $tbound1:ident $(+ $tbound2:ident)*)* $(, $typaram:ident : $bound:ident)*
>) => {
impl<T $(, $typaram)*> SchemaSerialize for $ty<T $(, $typaram)*>
where
T: SchemaSerialize $(+ $tbound1 $(+ $tbound2)*)*,
$($typaram: $bound,)*
{
#[inline]
fn schema_register<S: Schema>(schema: &mut S) -> Result<S::TypeId, S::Error> {
let id = T::schema_register(schema)?;
schema.register_type(Type::Seq(SeqType { len: None, element: id }))
}
}
}
}
seq_impl!(BinaryHeap<T: Ord>);
seq_impl!(BTreeSet<T: Ord>);
seq_impl!(HashSet<T: Eq + Hash, H: BuildHasher>);
seq_impl!(LinkedList<T>);
seq_impl!(Vec<T>);
seq_impl!(VecDeque<T>);
impl<Idx: SchemaSerialize> SchemaSerialize for ::std::ops::Range<Idx> {
fn schema_register<S: Schema>(schema: &mut S) -> Result<S::TypeId, S::Error> {
let id = Idx::schema_register(schema)?;
schema.register_type(Type::Struct(StructType {
name: Cow::Borrowed("Range"),
fields: Cow::Owned(vec![
StructField {
name: Cow::Borrowed("start"),
id: id.clone(),
},
StructField {
name: Cow::Borrowed("end"),
id,
},
]),
}))
}
}
impl SchemaSerialize for () {
#[inline]
fn schema_register<S: Schema>(_: &mut S) -> Result<S::TypeId, S::Error> {
Ok(TypeId::UNIT)
}
}
macro_rules! tuple_impls {
($($len:expr => ($($n:tt $name:ident)+))+) => {
$(
impl<$($name),+> SchemaSerialize for ($($name,)+)
where
$($name: SchemaSerialize,)+
{
#[inline]
fn schema_register<S: Schema>(schema: &mut S) -> Result<S::TypeId, S::Error> {
let elements = vec![
$(
$name::schema_register(schema)?,
)+
];
schema.register_type(Type::Tuple(TupleType { elements: Cow::Owned(elements) }))
}
}
)+
}
}
tuple_impls! {
1 => (0 T0)
2 => (0 T0 1 T1)
3 => (0 T0 1 T1 2 T2)
4 => (0 T0 1 T1 2 T2 3 T3)
5 => (0 T0 1 T1 2 T2 3 T3 4 T4)
6 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5)
7 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6)
8 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7)
9 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8)
10 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9)
11 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10)
12 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11)
13 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12)
14 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13)
15 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14)
16 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14
15 T15)
}
macro_rules! map_impl {
($ty:ident <
K $(: $kbound1:ident $(+ $kbound2:ident)*)*,
V $(, $typaram:ident : $bound:ident)*
>) => {
impl<K, V $(, $typaram)*> SchemaSerialize for $ty<K, V $(, $typaram)*>
where
K: SchemaSerialize $(+ $kbound1 $(+ $kbound2)*)*,
V: SchemaSerialize,
$($typaram: $bound,)*
{
#[inline]
fn schema_register<S: Schema>(schema: &mut S) -> Result<S::TypeId, S::Error> {
let k = K::schema_register(schema)?;
let v = V::schema_register(schema)?;
schema.register_type(Type::Map(MapType { key: k, value: v }))
}
}
}
}
map_impl!(BTreeMap<K: Ord, V>);
map_impl!(HashMap<K: Eq + Hash, V, H: BuildHasher>);
impl<'a, T: SchemaSerialize + ?Sized> SchemaSerialize for &'a T {
#[inline]
fn schema_register<S: Schema>(schema: &mut S) -> Result<S::TypeId, S::Error> {
T::schema_register(schema)
}
}
impl<'a, T: SchemaSerialize + ?Sized> SchemaSerialize for &'a mut T {
#[inline]
fn schema_register<S: Schema>(schema: &mut S) -> Result<S::TypeId, S::Error> {
T::schema_register(schema)
}
}
impl<T: SchemaSerialize + ?Sized> SchemaSerialize for Box<T> {
#[inline]
fn schema_register<S: Schema>(schema: &mut S) -> Result<S::TypeId, S::Error> {
T::schema_register(schema)
}
}
impl<'a, T: SchemaSerialize + ToOwned + ?Sized> SchemaSerialize for Cow<'a, T> {
#[inline]
fn schema_register<S: Schema>(schema: &mut S) -> Result<S::TypeId, S::Error> {
T::schema_register(schema)
}
}