openapiv3-resolve
Reference resolution helpers for the openapiv3 crate.
This crate adds traits that resolve $ref pointers (e.g.
#/components/schemas/Pet) against an OpenAPI document, returning a
borrowed reference to the resolved item. It walks chains of references
transparently, supports the boxed variant ReferenceOr<Box<T>> used by fields
such as ArrayType::items, and reports why a reference could not be resolved
instead of collapsing every failure into "not found".
Usage
use ;
use ;
Traits
Resolve— implemented onOpenAPI.openapi.resolve_ref::<Schema>(ptr)takes a full pointer like#/components/schemas/Pet. The type argument decides which section is searched.ResolveWithOpenAPI<T>— implemented onReferenceOr<T>andReferenceOr<Box<T>>; returns the inline item, or resolves the reference.ResolveOptionalWithOpenAPI<T>— implemented onOption<R>for any resolvableR;resolve_optionalreturnsOk(None)for an absent field and an error only for a reference that is present but broken.
Resolvable targets are the nine #/components sections plus #/paths, listed
by the Section enum. A $ref is read as a URI reference: the fragment is
percent-decoded first, then RFC 6901 unescaped, so the path /pets/{id} is
reachable as #/paths/~1pets~1%7Bid%7D.
The Component trait that maps a Rust type to its section is sealed, so the
two can never disagree. Note that openapiv3::Callback is a transparent alias
for IndexMap<String, PathItem> rather than a distinct type, so any value of
that shape resolves as a callback.
Errors
Every failure is a distinct ResolveError variant, so a caller can tell a
typo in the document (NotFound, SectionMismatch) from a reference this
crate structurally does not follow (ExternalDocument, PointerTooDeep) from
a document that is broken (ReferenceChainTooLong, which is what a cycle
looks like).
Reference chains are walked iteratively and capped at MAX_REFERENCE_HOPS, so
a cyclic document returns an error rather than overflowing the stack.
Thread safety
OpenAPI and every resolvable component are Send + Sync, resolution takes
&self, and the returned borrow is Send + Sync too — so a resolved reference
can be held across an .await in a Send future.
Resolving a #/components/... pointer allocates nothing, however long the
reference chain. Pointers carrying an escape (~0, ~1, %XX) are the
exception: the decoded name has to be built. Both are pinned by a test.
Minimum supported Rust version
1.85, which is the floor indexmap imposes rather than anything this crate
needs, and it is checked by its own CI job. A dependency raising its MSRV
raises this one; that is a minor version bump.
License
Licensed under the MIT license.