use schemars::{JsonSchema, Schema, SchemaGenerator};
use topcoat_router::content::{Form, Json};
pub trait Content {
const MEDIA_TYPE: &'static str;
const REQUIRED: bool = true;
fn schema(generator: &mut SchemaGenerator) -> Schema;
}
impl<T: JsonSchema> Content for Json<T> {
const MEDIA_TYPE: &'static str = "application/json";
fn schema(generator: &mut SchemaGenerator) -> Schema {
generator.subschema_for::<T>()
}
}
impl<T: JsonSchema> Content for Form<T> {
const MEDIA_TYPE: &'static str = "application/x-www-form-urlencoded";
fn schema(generator: &mut SchemaGenerator) -> Schema {
generator.subschema_for::<T>()
}
}
impl Content for String {
const MEDIA_TYPE: &'static str = "text/plain";
fn schema(generator: &mut SchemaGenerator) -> Schema {
generator.subschema_for::<String>()
}
}
impl Content for &str {
const MEDIA_TYPE: &'static str = "text/plain";
fn schema(generator: &mut SchemaGenerator) -> Schema {
generator.subschema_for::<String>()
}
}
impl<T: Content> Content for Option<T> {
const MEDIA_TYPE: &'static str = T::MEDIA_TYPE;
const REQUIRED: bool = false;
fn schema(generator: &mut SchemaGenerator) -> Schema {
T::schema(generator)
}
}
pub(crate) type SchemaFn = fn(&mut SchemaGenerator) -> Schema;
#[derive(Debug, Clone, Copy)]
pub(crate) struct ContentType {
pub(crate) media_type: &'static str,
pub(crate) required: bool,
pub(crate) schema: SchemaFn,
}
impl ContentType {
pub(crate) fn of<T: Content>() -> Self {
Self {
media_type: T::MEDIA_TYPE,
required: T::REQUIRED,
schema: T::schema,
}
}
}