in compiler-rs/openapi_to_clients_schema/src/types.rs [99:177]
fn generate_type_for_schema(
open_api: &OpenAPI,
id: &str,
schema: &Schema,
types: &mut Types,
) -> anyhow::Result<TypeName> {
if let Some(typedef) = types.get(id) {
// info!("Type '{id}' already generated");
return Ok(typedef.name().clone());
}
types.track(id);
// Build the common "base" fields from the OpenApi schema_data
let type_name = id_to_typename(id);
let data = &schema.schema_data;
let mut base = BaseType::new(type_name.clone());
base.description = data.description.clone();
if data.deprecated {
base.deprecation = Some(Deprecation {
version: "".into(),
description: "".into(),
})
}
if let Some(ref docs) = data.external_docs {
base.ext_doc_url = Some(docs.url.clone())
}
// TODO: data.readonly/writeonly -> OverloadOf?
// TODO: data.default -> serverDefault
// TODO: data.extensions -> see what's there, fail on unknown ones
for (k, v) in &data.extensions {
info!("{id} - extension {k} = {v}");
}
if data.discriminator.is_some() {
// FIXME: data.discriminator -> internally tagged variant
bail!(
"Discriminator in schema {} has to become an internally tagged variant",
id
);
}
use openapiv3::SchemaKind::*;
match &schema.schema_kind {
Type(t) => {
// Type alias to a primitive type or enum
generate_schema_kind_type(open_api, id, t, base, types)?;
}
Not { .. } => {
bail!("Unsupported schema kind for '{}' - {:?}", id, schema.schema_kind);
}
Any(any) => {
let not_any = Schema {
schema_data: data.clone(),
schema_kind: openapi::any_to_schema(any.clone())?,
};
generate_type_for_schema(open_api, id, ¬_any, types)?;
}
// Definitions:
// - oneOf: validates the value against exactly one of the subschemas
// - anyOf: validates the value against any (one or more) of the subschemas
// - allOf – validates the value against all the subschemas
//
// AnyOf sits in between oneOf and allOf and doesn't have a direct equivalence in schema.json
// We choose to handle it like a oneOf, even if oneOf is more constrained, as allOf is used for
// composition/inheritance.
AllOf { all_of } => {
let merged = open_api.merge_schemas(all_of, data)?;
generate_type_for_schema(open_api, id, &merged, types)?;
}
AnyOf { any_of: one_of } | OneOf { one_of } => {
generate_schema_kind_one_of(open_api, id, one_of, &data.discriminator, base, types)?;
}
}
Ok(type_name)
}