use std::mem;
use openapiv3::ObjectType;
use openapiv3::ReferenceOr;
use openapiv3::Schema;
use openapiv3::SchemaData;
use openapiv3::SchemaKind;
use openapiv3::Type;
use schemars::gen::SchemaGenerator as InnerGenerator;
use schemars::gen::SchemaSettings;
use schemars::JsonSchema;
use schemars::Map;
use crate::internals::convert_schema;
pub struct SchemaGenerator(InnerGenerator);
impl AsRef<InnerGenerator> for SchemaGenerator {
fn as_ref(&self) -> &InnerGenerator {
&self.0
}
}
impl AsMut<InnerGenerator> for SchemaGenerator {
fn as_mut(&mut self) -> &mut InnerGenerator {
&mut self.0
}
}
impl SchemaGenerator {
pub fn generate<T: JsonSchema>(&mut self) -> ReferenceOr<Schema> {
convert_schema(self.0.subschema_for::<T>())
}
pub fn generate_refless<T: JsonSchema>(&mut self) -> Result<Schema, String> {
let schema = convert_schema(T::json_schema(&mut self.0));
match schema {
ReferenceOr::Item(schema) => Ok(schema),
ReferenceOr::Reference { reference } => Err(reference),
}
}
pub fn generate_object<T: JsonSchema>(&mut self) -> Option<(ObjectType, SchemaData)> {
let schema = self.generate_refless::<T>().ok()?;
match schema.schema_kind {
SchemaKind::Type(Type::Object(obj)) => Some((obj, schema.schema_data)),
_ => None,
}
}
pub fn employ<T>(
definitions: &mut Map<String, schemars::schema::Schema>,
func: impl FnOnce(&mut Self) -> T,
) -> T {
let mut settings = SchemaSettings::openapi3();
settings.visitors = Vec::new();
let mut gen = Self(InnerGenerator::new(settings));
*gen.as_mut().definitions_mut() = mem::take(definitions);
let output = func(&mut gen);
*definitions = gen.as_mut().take_definitions();
output
}
}