@@ -31,29 +31,30 @@ appropriate built-in type based on type attributes. For example, a JSON Schema
31
31
might specify a maximum and/or minimum that indicates the appropriate integral
32
32
type to use.
33
33
34
- String schemas that include a ` format ` are represented with the appropriate Rust
35
- type. For example ` { "type": "string", "format": "uuid" } ` is represented as a
36
- ` uuid::Uuid ` (which requires the ` uuid ` crate be included as a dependency).
34
+ String schemas that include a known ` format ` are represented with the
35
+ appropriate Rust type. For example ` { "type": "string", "format": "uuid" } ` is
36
+ represented as a ` uuid::Uuid ` (which requires the ` uuid ` crate be included as a
37
+ dependency).
37
38
38
39
### Arrays
39
40
40
41
JSON Schema arrays can turn into one of three Rust types ` Vec<T> ` , ` HashSet<T> ` ,
41
42
and tuples depending on the schema properties. An array may have a fixed length
42
43
that matches a fixed list of item types; this is well represented by a Rust
43
- tuples . The distinction between ` Vec<T> ` and ` HashSet<T> ` is only if the
44
+ tuple . The distinction between ` Vec<T> ` and ` HashSet<T> ` is only if the
44
45
schema's ` uniqueItems ` field is ` false ` or ` true ` respectively.
45
46
46
47
### Objects
47
48
48
- In general, objects turn in to Rust structs. If, however, the schema defines no
49
+ In general, objects turn into Rust structs. If, however, the schema defines no
49
50
properties, Typify emits a ` HashMap<String, T> ` if the ` additionalProperties `
50
51
schema specifies ` T ` or a ` HashMap<String, serde_json::Value> ` otherwise.
51
52
52
- Properties that are not in the ` required ` set are typically represented as an
53
- ` Option<T> ` with the ` #[serde(default)] ` attribute applied. Non-required
54
- properties with types that already have a default value (such as a ` Vec<T> ` )
55
- simply get the ` #[serde(default)] ` attribute (so you won't see e.g.
56
- ` Option<Vec<T>> ` ).
53
+ Properties of generated ` struct ` that are not in the ` required ` set are
54
+ typically represented as an ` Option<T> ` with the ` #[serde(default)] ` attribute
55
+ applied. Non-required properties with types that already have a default value
56
+ (such as a ` Vec<T> ` ) simply get the ` #[serde(default)] ` attribute (so you won't
57
+ see e.g. ` Option<Vec<T>> ` ).
57
58
58
59
### OneOf
59
60
@@ -76,6 +77,166 @@ flattened members, this is one of the weaker areas of code generation.
76
77
77
78
Issues describing example schemas and desired output are welcome and helpful.
78
79
80
+ ## Rust -> Schema -> Rust
81
+
82
+ Schemas derived from Rust types may include an extension that provides
83
+ information about the original type:
84
+
85
+ ``` json
86
+ {
87
+ "type" : " object" ,
88
+ "properties" : { .. },
89
+ "x-rust-type" : {
90
+ "crate" : " crate-o-types" ,
91
+ "version" : " 1.0.0" ,
92
+ "path" : " crate_o_types::some_mod::SomeType"
93
+ }
94
+ }
95
+ ```
96
+
97
+ The extension includes the name of the crate, a Cargo-style version
98
+ requirements spec, and the full path (that must start with ident-converted name
99
+ of the crate).
100
+
101
+ Each of the modes of using typify allow for a list of crates and versions to be
102
+ specified. In this case, if the user specifies "
[email protected] " for
103
+ example, then typify would use its ` SomeType ` type rather than generating one
104
+ according to the schema.
105
+
106
+ ### Using types from other crates
107
+
108
+ Each mode of using typify has a method for controlling the use of types with
109
+ ` x-rust-type ` annotations. The default is to ignore them. The recommended
110
+ method is to specify each crate and version you intend to use. You can
111
+ additionally supply the ` * ` version for crates (which may result in
112
+ incompatibilities) or you can define a policy to allow the use of all "unknown"
113
+ crates (which may require that addition of dependencies for those crates).
114
+
115
+ For the CLI:
116
+ ``` console
117
+ $
cargo typify --unknown-crates allow --crate [email protected] ...
118
+ ```
119
+
120
+ For the builder:
121
+ ``` rust
122
+ let mut settings = typify :: TypeSpaceSettings :: default ();
123
+ settings . with_unknown_crates (typify :: UnknownPolicy :: Allow )
124
+ . with_crate (" oxnet" , typify :: CrateVers :: Version (" 1.0.0" . parse (). unwrap ()));
125
+ ```
126
+
127
+ For the macro:
128
+ ``` rust
129
+ typify :: import_types! (
130
+ schema = " schema.json" ,
131
+ unknown_types = Allow ,
132
+ crates {
133
+ " oxnet" = " 1.0.0"
134
+ }
135
+ )
136
+ ```
137
+
138
+ ### Version requirements
139
+
140
+ The ` version ` field within the ` x-rust-type ` extension follows the Cargo
141
+ version requirements specification. If the extension specifies ` 0.1.0 ` of a
142
+ crate and the user states that they're using ` 0.1.1 ` , then the type is used;
143
+ conversely, if the extension specifies ` 0.2.2 ` and the user is only using
144
+ ` 0.2.0 ` the type is not used.
145
+
146
+ Crate authors may choose to adhere to greater stability than otherwise provided
147
+ by semver. If the extension version is ` >=0.1.0, <1.0.0 ` then the crate author
148
+ is committing to the schema compatibility of the given type on all releases
149
+ until ` 1.0.0 ` . It is important that crate authors populate the ` version ` field
150
+ in a way that upholds type availability. For example, while ` * ` is a valid
151
+ value, it is only conceivably valid if the type in question were available in
152
+ the first ever version of a crate published and never changed incompatibly in
153
+ any subsequent version.
154
+
155
+ ### Type parameters
156
+
157
+ The ` x-rust-type ` extension may also specify type parameters:
158
+
159
+ ``` json
160
+ {
161
+ "$defs" : {
162
+ "Sprocket" : {
163
+ "type" : " object" ,
164
+ "properties" : { .. },
165
+ "x-rust-type" : {
166
+ "crate" : " util" ,
167
+ "version" : " 0.1.0" ,
168
+ "path" : " util::Sprocket" ,
169
+ "parameters" : [
170
+ {
171
+ "$ref" : " #/$defs/Gizmo"
172
+ }
173
+ ]
174
+ }
175
+ },
176
+ "Gizmo" : {
177
+ "type" : " object" ,
178
+ "properties" : { .. },
179
+ "x-rust-type" : {
180
+ "crate" : " util" ,
181
+ "version" : " 0.1.0" ,
182
+ "path" : " util::Gizmo"
183
+ }
184
+ }
185
+ }
186
+ }
187
+ ```
188
+
189
+ With the
` [email protected] ` crate specified during type generation, schemas
190
+ referencing ` #/$defs/Sprocket ` would use the (non-generated) type
191
+ ` util::Sprocket<util::Gizmo> ` .
192
+
193
+ The ` parameters ` field is an array of schemas. They may be inline schemas or
194
+ referenced schemas.
195
+
196
+ ### Including ` x-rust-type ` in your library
197
+
198
+ The schema for the expected value is as follows:
199
+
200
+ ``` json
201
+ {
202
+ "description" : " schema for the x-rust-type extension" ,
203
+ "type" : " object" ,
204
+ "properties" : {
205
+ "crate" : {
206
+ "type" : " string" ,
207
+ "pattern" : " ^[a-zA-Z0-9_-]+$"
208
+ },
209
+ "version" : {
210
+ "description" : " semver requirements per a Cargo.toml dependencies entry" ,
211
+ "type" : " string"
212
+ },
213
+ "path" : {
214
+ "type" : " string" ,
215
+ "pattern" : " ^[a-zA-Z0-9_]+(::[a-zA-Z0-9+]+)*$"
216
+ },
217
+ "parameters" : {
218
+ "type" : " array" ,
219
+ "items" : {
220
+ "$ref" : " #/definitions/Schema"
221
+ }
222
+ }
223
+ },
224
+ "required" : [
225
+ " crate" ,
226
+ " path" ,
227
+ " version"
228
+ ]
229
+ }
230
+ ```
231
+
232
+ The ` version ` field expresses the stability of your type. For example, if
233
+ ` 0.1.0 ` indicates that ` 0.1.1 ` users would be fine whereas ` 0.2.0 ` users would
234
+ not use the type (instead generating it). You can communicate a future
235
+ commitment beyond what semver implies by using the [ Cargo version requirement
236
+ syntax] ( https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#version-requirement-syntax ) .
237
+ For example ` >=0.1.0, <1.0.0 ` says that the type will remain structurally
238
+ compatible from version ` 0.1.0 ` until ` 1.0.0 ` .
239
+
79
240
## Formatting
80
241
81
242
You can format generated code using crates such as
@@ -90,7 +251,7 @@ The examples below show different ways to convert a `TypeSpace` to a string
90
251
### ` rustfmt `
91
252
92
253
Best for generation of code that might be checked in alongside hand-written
93
- code such as in the case of an ` xtask ` or stand-alone code generator (list
254
+ code such as in the case of an ` xtask ` or stand-alone code generator (such as
94
255
` cargo-typify ` ).
95
256
96
257
``` rust
0 commit comments