Skip to main content

openapiv3_resolve/resolved/
mod.rs

1//! A whole document with every `$ref` followed, for callers that would rather
2//! walk a plain tree than resolve at each site.
3
4mod cache;
5mod components;
6mod discriminator;
7mod document;
8mod operation;
9mod parameter;
10mod resolver;
11mod response;
12mod schema;
13mod schema_type;
14mod shared;
15
16pub use components::ResolvedComponents;
17pub use discriminator::ResolvedDiscriminator;
18pub use document::{ResolvedCallback, ResolvedOpenAPI, ResolvedPathItem, ResolvedPaths};
19pub use operation::{ResolvedOperation, ResolvedResponses};
20pub use parameter::{
21    ResolvedHeader, ResolvedParameter, ResolvedParameterData, ResolvedParameterSchemaOrContent,
22};
23pub use response::{ResolvedEncoding, ResolvedMediaType, ResolvedRequestBody, ResolvedResponse};
24pub use schema::{
25    ResolvedAdditionalProperties, ResolvedSchema, ResolvedSchemaData, ResolvedSchemaKind,
26};
27pub use schema_type::{ResolvedAnySchema, ResolvedArrayType, ResolvedObjectType, ResolvedType};
28pub use shared::{NestedSchema, SchemaGuard, Shared};
29
30use crate::ResolveError;
31use indexmap::IndexMap;
32use openapiv3::{Example, Link, OpenAPI, SecurityScheme};
33use resolver::{Resolvable, Resolver};
34
35impl TryFrom<&OpenAPI> for ResolvedOpenAPI {
36    type Error = ResolveError;
37
38    /// Resolves every `$ref` in the document.
39    ///
40    /// Fails with the first reference that does not resolve. A schema that
41    /// contains a reference back to itself is fine, and comes out with a
42    /// [`NestedSchema`] edge that is recursive; any other component that
43    /// contains itself has no finite tree form and fails with
44    /// [`ResolveError::CyclicReference`].
45    fn try_from(openapi: &OpenAPI) -> Result<Self, Self::Error> {
46        openapi.resolve_inline(&mut Resolver::new(openapi))
47    }
48}
49
50impl TryFrom<OpenAPI> for ResolvedOpenAPI {
51    type Error = ResolveError;
52
53    fn try_from(openapi: OpenAPI) -> Result<Self, Self::Error> {
54        Self::try_from(&openapi)
55    }
56}
57
58/// Resolves every value of a map of inline items, keeping keys and order.
59fn resolve_map<T: Resolvable>(
60    map: &IndexMap<String, T>,
61    cx: &mut Resolver<'_>,
62) -> Result<IndexMap<String, T::Resolved>, ResolveError> {
63    map.iter()
64        .map(|(key, value)| Ok((key.clone(), value.resolve_inline(cx)?)))
65        .collect()
66}
67
68macro_rules! reference_free {
69    ($($ty:ty),+ $(,)?) => {
70        $(
71            impl Resolvable for $ty {
72                type Resolved = Self;
73
74                fn resolve_inline(&self, _: &mut Resolver<'_>) -> Result<Self, ResolveError> {
75                    Ok(self.clone())
76                }
77            }
78        )+
79    };
80}
81
82// These hold no `$ref`, so upstream's type already is the resolved form.
83reference_free!(Example, Link, SecurityScheme);