use crate::parser::{Request, SchemaType};
use std::collections::{BTreeMap, BTreeSet};
pub struct ModelData {
pub definitions: BTreeMap<String, SchemaType>,
pub names: BTreeSet<String>,
}
pub fn prepare_model_data(requests: &[Request]) -> ModelData {
let mut model_definitions: BTreeMap<String, SchemaType> = BTreeMap::new();
let mut model_names: BTreeSet<String> = BTreeSet::new();
for req in requests {
add_models_from_request(req, &mut model_definitions, &mut model_names);
}
for model_name in model_definitions.keys() {
model_names.insert(model_name.to_string());
}
ModelData {
definitions: model_definitions,
names: model_names,
}
}
fn add_models_from_request(
req: &Request,
model_definitions: &mut BTreeMap<String, SchemaType>,
model_names: &mut BTreeSet<String>,
) {
add_models_from_params(req, model_names);
add_models_from_body(req, model_definitions, model_names);
add_models_from_responses(req, model_definitions, model_names);
}
fn add_models_from_params(req: &Request, model_names: &mut BTreeSet<String>) {
if let Some(params) = &req.params {
for param in params {
if let Some(schema_type) = ¶m.schema_type {
collect_ref_names(schema_type, model_names);
}
}
}
}
fn add_models_from_body(
req: &Request,
model_definitions: &mut BTreeMap<String, SchemaType>,
model_names: &mut BTreeSet<String>,
) {
if let Some(body) = &req.body {
register_named_schema(
body.schema_name.as_ref(),
body.schema_type.as_ref(),
model_definitions,
model_names,
);
if let Some(schema_type) = &body.schema_type {
collect_ref_names(schema_type, model_names);
}
}
}
fn add_models_from_responses(
req: &Request,
model_definitions: &mut BTreeMap<String, SchemaType>,
model_names: &mut BTreeSet<String>,
) {
if let Some(responses) = &req.responses {
for response in responses.values() {
register_named_schema(
response.schema_name.as_ref(),
response.schema_type.as_ref(),
model_definitions,
model_names,
);
if let Some(schema_type) = &response.schema_type {
collect_ref_names(schema_type, model_names);
}
}
}
}
fn register_named_schema(
schema_name: Option<&String>,
schema_type: Option<&SchemaType>,
model_definitions: &mut BTreeMap<String, SchemaType>,
model_names: &mut BTreeSet<String>,
) {
let Some(name) = schema_name else {
return;
};
model_names.insert(name.clone());
if let Some(schema_type) = schema_type {
model_definitions
.entry(name.clone())
.or_insert_with(|| schema_type.clone());
}
}
fn collect_ref_names(schema: &SchemaType, names: &mut BTreeSet<String>) {
match schema {
SchemaType::Ref(name) => {
names.insert(name.clone());
}
SchemaType::Array(inner) => collect_ref_names(inner, names),
SchemaType::Object(obj) => {
for value in obj.properties.values() {
collect_ref_names(value, names);
}
}
SchemaType::OneOf(variants)
| SchemaType::AnyOf(variants)
| SchemaType::AllOf(variants) => {
for variant in variants {
collect_ref_names(variant, names);
}
}
SchemaType::Primitive(_) | SchemaType::Unknown => {}
}
}