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