use indexmap::IndexMap;
use utoipa::openapi::{RefOr, Schema};
use super::string::AsStr;
pub trait SchemaExt {
fn get_schema_props(&self) -> IndexMap<String, Schema>;
fn default_description<Desc: Into<String>>(self, default_description: Desc) -> Self;
fn get_description(&self) -> &str;
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(),
}
}
}