use super::discriminator::resolve_discriminator;
use super::resolver::{Resolvable, Resolver};
use super::{NestedSchema, ResolvedAnySchema, ResolvedDiscriminator, ResolvedType};
use crate::ResolveError;
use indexmap::IndexMap;
use openapiv3::{AdditionalProperties, ExternalDocumentation, Schema, SchemaData, SchemaKind};
#[derive(Debug, PartialEq)]
pub struct ResolvedSchema {
pub schema_data: ResolvedSchemaData,
pub schema_kind: ResolvedSchemaKind,
}
#[derive(Debug, Default, PartialEq)]
pub struct ResolvedSchemaData {
pub nullable: bool,
pub read_only: bool,
pub write_only: bool,
pub deprecated: bool,
pub external_docs: Option<ExternalDocumentation>,
pub example: Option<serde_json::Value>,
pub title: Option<String>,
pub description: Option<String>,
pub discriminator: Option<ResolvedDiscriminator>,
pub default: Option<serde_json::Value>,
pub extensions: IndexMap<String, serde_json::Value>,
}
#[derive(Debug, PartialEq)]
pub enum ResolvedSchemaKind {
Type(ResolvedType),
OneOf {
one_of: Vec<NestedSchema>,
},
AllOf {
all_of: Vec<NestedSchema>,
},
AnyOf {
any_of: Vec<NestedSchema>,
},
Not {
not: NestedSchema,
},
Any(Box<ResolvedAnySchema>),
}
#[derive(Debug, PartialEq)]
pub enum ResolvedAdditionalProperties {
Any(bool),
Schema(NestedSchema),
}
impl Resolvable for Schema {
type Resolved = ResolvedSchema;
fn resolve_inline(&self, cx: &mut Resolver<'_>) -> Result<Self::Resolved, ResolveError> {
let schema_kind = self.schema_kind.resolve_inline(cx)?;
let discriminator = self
.schema_data
.discriminator
.as_ref()
.map(|discriminator| {
resolve_discriminator(cx, discriminator, &self.schema_kind, &schema_kind)
})
.transpose()?;
Ok(ResolvedSchema {
schema_data: resolve_schema_data(&self.schema_data, discriminator),
schema_kind,
})
}
}
impl Resolvable for SchemaKind {
type Resolved = ResolvedSchemaKind;
fn resolve_inline(&self, cx: &mut Resolver<'_>) -> Result<Self::Resolved, ResolveError> {
Ok(match self {
Self::Type(kind) => ResolvedSchemaKind::Type(kind.resolve_inline(cx)?),
Self::OneOf { one_of } => ResolvedSchemaKind::OneOf {
one_of: cx.nested_vec(one_of)?,
},
Self::AllOf { all_of } => ResolvedSchemaKind::AllOf {
all_of: cx.nested_vec(all_of)?,
},
Self::AnyOf { any_of } => ResolvedSchemaKind::AnyOf {
any_of: cx.nested_vec(any_of)?,
},
Self::Not { not } => ResolvedSchemaKind::Not {
not: cx.nested(not)?,
},
Self::Any(any) => ResolvedSchemaKind::Any(Box::new(any.resolve_inline(cx)?)),
})
}
}
impl Resolvable for AdditionalProperties {
type Resolved = ResolvedAdditionalProperties;
fn resolve_inline(&self, cx: &mut Resolver<'_>) -> Result<Self::Resolved, ResolveError> {
Ok(match self {
Self::Any(allowed) => ResolvedAdditionalProperties::Any(*allowed),
Self::Schema(schema) => ResolvedAdditionalProperties::Schema(cx.nested(schema)?),
})
}
}
fn resolve_schema_data(
data: &SchemaData,
discriminator: Option<ResolvedDiscriminator>,
) -> ResolvedSchemaData {
let SchemaData {
nullable,
read_only,
write_only,
deprecated,
external_docs,
example,
title,
description,
discriminator: _,
default,
extensions,
} = data;
ResolvedSchemaData {
nullable: *nullable,
read_only: *read_only,
write_only: *write_only,
deprecated: *deprecated,
external_docs: external_docs.clone(),
example: example.clone(),
title: title.clone(),
description: description.clone(),
discriminator,
default: default.clone(),
extensions: extensions.clone(),
}
}