Skip to main content

openapi_type/
lib.rs

1#![allow(clippy::tabs_in_doc_comments)]
2#![warn(missing_debug_implementations, rust_2018_idioms)]
3#![deny(rustdoc::broken_intra_doc_links)]
4#![forbid(elided_lifetimes_in_paths, unsafe_code)]
5#![doc = r##"
6This crate gives static type information for primitives and commonly used types from the
7standard library and other commonly used libraries [`chrono`], [`hashbrown`],
8[`indexmap`], [`linked-hash-map`], [`time`] and [`uuid`] when the according feature is
9enabled. Please refer to the [`Cargo.toml`] for a list of all available feature flags and
10optional dependencies. Also, it provides a derive macro for structs and enums to gain
11access to their static type information at runtime.
12
13The core of this crate is the [`OpenapiType`] trait. It has one static function,
14[`schema`](OpenapiType::schema), which returns an [`OpenapiSchema`]. This assembles the
15static type information in a way that is convenient to use for a generated OpenAPI
16specification, but can also be utilized in other use cases as well.
17
18# Custom Types
19
20To gain access to the static type information of your custom types at runtime, the easiest
21way is to use the derive macro:
22
23```rust
24# use openapi_type::OpenapiType;
25#[derive(OpenapiType)]
26struct FooBar {
27	foo: String,
28	bar: u64
29}
30# let schema = FooBar::schema();
31# let schema_json = serde_json::to_value(&schema.schema).unwrap();
32# assert_eq!(schema_json, serde_json::json!({
33#   "type": "object",
34#   "title": "FooBar",
35#   "properties": {
36#     "foo": {
37#       "type": "string"
38#     },
39#     "bar": {
40#       "type": "integer",
41#       "format": "int64",
42#       "minimum": 0
43#     }
44#   },
45#   "required": ["foo", "bar"]
46# }));
47```
48
49# OpenAPI specification
50
51Using above type, running `FooBar::schema().into_schema()` yields
52
53```yaml
54type: object
55title: FooBar
56properties:
57  foo:
58    type: string
59  bar:
60    type: integer
61    format: int64
62    minimum: 0
63required:
64  - foo
65  - bar
66```
67
68Note, however, that this is not sufficient for more complex types. If one of your structs
69fields is a type that has a name (that is, `Type::schema().name` is not `None`), above
70schema will contain a reference to that schema. Therefore, always remember to put the
71[`dependencies`](OpenapiSchema::dependencies) into the specification alongside the type
72you are interested in.
73
74 [`Cargo.toml`]: https://docs.rs/crate/openapi_type/latest/source/Cargo.toml.orig
75 [`chrono`]: https://crates.io/crates/chrono
76 [`hashbrown`]: https://crates.io/crates/hashbrown
77 [`indexmap`]: https://crates.io/crates/indexmap
78 [`linked-hash-map`]: https://crates.io/crates/linked-hash-map
79 [`time`]: https://crates.io/crates/time
80 [`uuid`]: https://crates.io/crates/uuid
81"##]
82
83pub use indexmap;
84pub use openapi_type_derive::OpenapiType;
85pub use openapiv3;
86
87mod impls;
88mod visitor;
89
90pub use visitor::{
91	AlternativesVisitor, ObjectVisitor, OpenapiSchema, OpenapiVisitor, Visitor
92};
93
94/// This trait needs to be implemented by every type that is being used in the OpenAPI Spec. It gives
95/// access to the [OpenapiSchema] of this type. It is provided for primitive types, String and the
96/// like. For use on your own types, there is a derive macro:
97///
98/// ```
99/// # #[macro_use] extern crate openapi_type_derive;
100/// #
101/// #[derive(OpenapiType)]
102/// struct MyResponse {
103/// 	message: String
104/// }
105/// ```
106pub trait OpenapiType {
107	fn visit_type<V: Visitor>(visitor: &mut V);
108
109	fn schema() -> OpenapiSchema {
110		let mut visitor = OpenapiVisitor::new();
111		Self::visit_type(&mut visitor);
112		visitor
113			.into_schema()
114			.expect("The OpenapiType implementation failed to call the visitor")
115	}
116}
117
118impl<T: ?Sized + OpenapiType> OpenapiType for &T {
119	fn visit_type<V: Visitor>(visitor: &mut V) {
120		T::visit_type(visitor)
121	}
122}