tina-core 0.0.2

Tina platform
Documentation
//! Schema 扩展

use indexmap::IndexMap;
use utoipa::openapi::{RefOr, Schema};

use super::string::AsStr;

/// Schema扩展
pub trait SchemaExt {
    /// 获取Schema的属性
    fn get_schema_props(&self) -> IndexMap<String, Schema>;
    /// 设置Schema的默认描述
    fn default_description<Desc: Into<String>>(self, default_description: Desc) -> Self;
    /// 获取Schema的描述
    fn get_description(&self) -> &str;
    /// 获取Schema的必填属性
    fn get_required(&self) -> Vec<String>;
}

impl SchemaExt for Schema {
    fn get_schema_props(&self) -> IndexMap<String, Schema> {
        match &self {
            Schema::Array(v) => match &*v.items {
                RefOr::<Schema>::Ref(v) => panic!("schema type cannot be $refs for 'get_schema_props': {:?}", v),
                RefOr::<Schema>::T(v) => v.get_schema_props(),
            },
            Schema::Object(v) => v
                .properties
                .iter()
                .map(|(k, v)| match &v {
                    RefOr::<Schema>::Ref(v) => panic!("schema type cannot be $refs for 'get_schema_props': {:?}", v),
                    RefOr::<Schema>::T(v) => (k.clone(), v.clone()),
                })
                .collect(),
            Schema::OneOf(v) => v
                .items
                .iter()
                .map(|v| match &v {
                    RefOr::<Schema>::Ref(v) => panic!("schema type cannot be $refs for 'get_schema_props': {:?}", v),
                    RefOr::<Schema>::T(v) => v.get_schema_props(),
                })
                .fold(IndexMap::new(), |mut m, m1| {
                    m.extend(m1.into_iter());
                    m
                }),
            Schema::AllOf(v) => v
                .items
                .iter()
                .map(|v| match &v {
                    RefOr::<Schema>::Ref(v) => panic!("schema type cannot be $refs for 'get_schema_props': {:?}", v),
                    RefOr::<Schema>::T(v) => v.get_schema_props(),
                })
                .fold(IndexMap::new(), |mut m, m1| {
                    m.extend(m1.into_iter());
                    m
                }),
            _ => unreachable!(),
        }
    }

    fn default_description<Desc: Into<String>>(self, default_description: Desc) -> Self {
        match self {
            Schema::Array(mut v) => {
                if v.description.as_str().is_empty() {
                    v.description = Some(default_description.into());
                }
                Schema::Array(v)
            }
            Schema::Object(mut v) => {
                if v.description.as_str().is_empty() {
                    v.description = Some(default_description.into());
                }
                Schema::Object(v)
            }
            Schema::OneOf(mut v) => {
                if v.description.as_str().is_empty() {
                    v.description = Some(default_description.into());
                }
                Schema::OneOf(v)
            }
            Schema::AllOf(mut v) => {
                if v.description.as_str().is_empty() {
                    v.description = Some(default_description.into());
                }
                Schema::AllOf(v)
            }
            _ => self,
        }
    }

    fn get_description(&self) -> &str {
        match &self {
            Schema::Array(v) => v.description.as_str(),
            Schema::Object(v) => v.description.as_str(),
            Schema::OneOf(v) => v.description.as_str(),
            Schema::AllOf(v) => v.description.as_str(),
            _ => "",
        }
    }

    fn get_required(&self) -> Vec<String> {
        match &self {
            Schema::Array(v) => v.items.get_required(),
            Schema::Object(v) => v.required.clone(),
            Schema::OneOf(v) => v.items.iter().map(|v| v.get_required()).fold(Vec::new(), |mut l, mut v| {
                l.append(&mut v);
                l
            }),
            Schema::AllOf(v) => v.items.iter().map(|v| v.get_required()).fold(Vec::new(), |mut l, mut v| {
                l.append(&mut v);
                l
            }),
            _ => vec![],
        }
    }
}

impl SchemaExt for RefOr<Schema> {
    fn get_schema_props(&self) -> IndexMap<String, Schema> {
        match &self {
            RefOr::<Schema>::Ref(v) => panic!("schema type cannot be $refs for 'get_schema_props': {:?}", v),
            RefOr::<Schema>::T(v) => v.get_schema_props(),
        }
    }

    fn default_description<Desc: Into<String>>(self, default_description: Desc) -> Self {
        match self {
            RefOr::<Schema>::Ref(v) => panic!("schema type cannot be $refs for 'default_description': {:?}", v),
            RefOr::<Schema>::T(v) => RefOr::T(v.default_description(default_description)),
        }
    }

    fn get_description(&self) -> &str {
        match self {
            RefOr::<Schema>::Ref(v) => panic!("schema type cannot be $refs for 'get_description': {:?}", v),
            RefOr::<Schema>::T(v) => v.get_description(),
        }
    }

    fn get_required(&self) -> Vec<String> {
        match self {
            RefOr::<Schema>::Ref(v) => panic!("schema type cannot be $refs for 'get_required': {:?}", v),
            RefOr::<Schema>::T(v) => v.get_required(),
        }
    }
}