use super::resolver::{Resolvable, Resolver};
use super::{ResolvedComponents, ResolvedOperation, ResolvedParameter, Shared};
use crate::ResolveError;
use indexmap::IndexMap;
use openapiv3::{
Callback, ExternalDocumentation, Info, OpenAPI, Operation, PathItem, Paths,
SecurityRequirement, Server, Tag,
};
#[derive(Debug, PartialEq)]
pub struct ResolvedOpenAPI {
openapi: String,
info: Info,
servers: Vec<Server>,
paths: ResolvedPaths,
components: Option<ResolvedComponents>,
security: Option<Vec<SecurityRequirement>>,
tags: Vec<Tag>,
external_docs: Option<ExternalDocumentation>,
extensions: IndexMap<String, serde_json::Value>,
}
impl ResolvedOpenAPI {
pub fn openapi(&self) -> &str {
&self.openapi
}
pub fn info(&self) -> &Info {
&self.info
}
pub fn servers(&self) -> &[Server] {
&self.servers
}
pub fn paths(&self) -> &ResolvedPaths {
&self.paths
}
pub fn components(&self) -> Option<&ResolvedComponents> {
self.components.as_ref()
}
pub fn security(&self) -> Option<&[SecurityRequirement]> {
self.security.as_deref()
}
pub fn tags(&self) -> &[Tag] {
&self.tags
}
pub fn external_docs(&self) -> Option<&ExternalDocumentation> {
self.external_docs.as_ref()
}
pub fn extensions(&self) -> &IndexMap<String, serde_json::Value> {
&self.extensions
}
}
#[derive(Debug, PartialEq)]
pub struct ResolvedPaths {
pub paths: IndexMap<String, Shared<ResolvedPathItem>>,
pub extensions: IndexMap<String, serde_json::Value>,
}
#[derive(Debug, PartialEq)]
pub struct ResolvedPathItem {
pub summary: Option<String>,
pub description: Option<String>,
pub get: Option<ResolvedOperation>,
pub put: Option<ResolvedOperation>,
pub post: Option<ResolvedOperation>,
pub delete: Option<ResolvedOperation>,
pub options: Option<ResolvedOperation>,
pub head: Option<ResolvedOperation>,
pub patch: Option<ResolvedOperation>,
pub trace: Option<ResolvedOperation>,
pub servers: Vec<Server>,
pub parameters: Vec<Shared<ResolvedParameter>>,
pub extensions: IndexMap<String, serde_json::Value>,
}
impl ResolvedPathItem {
pub fn iter(&self) -> impl Iterator<Item = (&'static str, &ResolvedOperation)> {
[
("get", &self.get),
("put", &self.put),
("post", &self.post),
("delete", &self.delete),
("options", &self.options),
("head", &self.head),
("patch", &self.patch),
("trace", &self.trace),
]
.into_iter()
.filter_map(|(method, operation)| operation.as_ref().map(|operation| (method, operation)))
}
}
pub type ResolvedCallback = IndexMap<String, ResolvedPathItem>;
impl Resolvable for OpenAPI {
type Resolved = ResolvedOpenAPI;
fn resolve_inline(&self, cx: &mut Resolver<'_>) -> Result<Self::Resolved, ResolveError> {
Ok(ResolvedOpenAPI {
openapi: self.openapi.clone(),
info: self.info.clone(),
servers: self.servers.clone(),
components: self
.components
.as_ref()
.map(|components| components.resolve_inline(cx))
.transpose()?,
paths: self.paths.resolve_inline(cx)?,
security: self.security.clone(),
tags: self.tags.clone(),
external_docs: self.external_docs.clone(),
extensions: self.extensions.clone(),
})
}
}
impl Resolvable for Paths {
type Resolved = ResolvedPaths;
fn resolve_inline(&self, cx: &mut Resolver<'_>) -> Result<Self::Resolved, ResolveError> {
Ok(ResolvedPaths {
paths: cx.section(&self.paths)?,
extensions: self.extensions.clone(),
})
}
}
impl Resolvable for PathItem {
type Resolved = ResolvedPathItem;
fn resolve_inline(&self, cx: &mut Resolver<'_>) -> Result<Self::Resolved, ResolveError> {
let mut operation = |operation: &Option<Operation>| {
operation
.as_ref()
.map(|operation| operation.resolve_inline(cx))
.transpose()
};
let get = operation(&self.get)?;
let put = operation(&self.put)?;
let post = operation(&self.post)?;
let delete = operation(&self.delete)?;
let options = operation(&self.options)?;
let head = operation(&self.head)?;
let patch = operation(&self.patch)?;
let trace = operation(&self.trace)?;
Ok(ResolvedPathItem {
summary: self.summary.clone(),
description: self.description.clone(),
get,
put,
post,
delete,
options,
head,
patch,
trace,
servers: self.servers.clone(),
parameters: cx.ref_or_vec(&self.parameters)?,
extensions: self.extensions.clone(),
})
}
}
impl Resolvable for Callback {
type Resolved = ResolvedCallback;
fn resolve_inline(&self, cx: &mut Resolver<'_>) -> Result<Self::Resolved, ResolveError> {
super::resolve_map(self, cx)
}
}