autapi 0.0.1

Automatic OpenAPI specification from function signatures
Documentation
use std::borrow::Cow;

use serde::{Deserializer, Serializer, ser::Error as _};

use crate::{
    Registry,
    openapi::{MaybeRef, Schema},
    schema::{SchemaDeserialize, SchemaSerialize, SchemaUsing, ToSchema},
};

impl<T: ToSchema> ToSchema for Option<T> {
    type Original = Option<T::Original>;

    const REQUIRED: bool = false;
    const ALWAYS_INLINED: bool = T::ALWAYS_INLINED;

    fn name() -> Cow<'static, str> {
        T::name()
    }
    fn schema(registry: &mut Registry) -> MaybeRef<Schema> {
        T::schema(registry)
    }
}

impl<T> SchemaSerialize for Option<T>
where
    T: SchemaSerialize,
{
    fn schema_serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let value: &T = self
            .as_ref()
            .ok_or_else(|| S::Error::custom("schema_serialize called for an absent value"))?;
        value.schema_serialize(serializer)
    }

    fn is_present(&self) -> bool {
        match &self {
            Some(value) => value.is_present(),
            None => false,
        }
    }
}

impl<T: SchemaDeserialize> SchemaDeserialize for Option<T> {
    fn schema_deserialize<'de, D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        Ok(Some(<T as SchemaDeserialize>::schema_deserialize(
            deserializer,
        )?))
    }
    fn deserialize_missing() -> Option<Self> {
        Some(None)
    }
}

impl<T> SchemaUsing<Option<T>> for T
where
    T: Default + ToSchema,
{
    type Ser<'a>
        = Option<&'a T>
    where
        T: 'a;

    fn to_ser<'a>(&'a self) -> Self::Ser<'a> {
        Some(self)
    }

    fn from_de(de: Option<T>) -> Self {
        de.unwrap_or_default()
    }
}