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