json_schema_rs/json_schema/
spec_version.rs1use super::settings::JsonSchemaSettings;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7pub enum SpecVersion {
8 Draft00,
9 Draft01,
10 Draft02,
11 Draft03,
12 Draft04,
13 Draft05,
14 Draft06,
15 Draft07,
16 Draft201909,
17 Draft202012,
18}
19
20impl SpecVersion {
21 #[must_use]
26 pub fn schema_uri(self) -> &'static str {
27 match self {
28 SpecVersion::Draft00 => "http://json-schema.org/draft-00/hyper-schema#",
29 SpecVersion::Draft01 => "http://json-schema.org/draft-01/hyper-schema#",
30 SpecVersion::Draft02 => "http://json-schema.org/draft-02/hyper-schema#",
31 SpecVersion::Draft03 => "http://json-schema.org/draft-03/schema#",
32 SpecVersion::Draft04 => "http://json-schema.org/draft-04/schema#",
33 SpecVersion::Draft05 => "http://json-schema.org/draft-05/schema#",
34 SpecVersion::Draft06 => "http://json-schema.org/draft-06/schema#",
35 SpecVersion::Draft07 => "http://json-schema.org/draft-07/schema#",
36 SpecVersion::Draft201909 => "https://json-schema.org/draft/2019-09/schema",
37 SpecVersion::Draft202012 => "https://json-schema.org/draft/2020-12/schema",
38 }
39 }
40
41 #[must_use]
49 pub fn from_schema_uri(s: &str) -> Option<SpecVersion> {
50 let s = s.trim();
51 if s.is_empty() {
52 return None;
53 }
54 let s_normalized = s.trim_end_matches('/');
56 match s_normalized {
57 "http://json-schema.org/draft-00/hyper-schema#" => Some(SpecVersion::Draft00),
58 "http://json-schema.org/draft-01/hyper-schema#" => Some(SpecVersion::Draft01),
59 "http://json-schema.org/draft-02/hyper-schema#" => Some(SpecVersion::Draft02),
60 "http://json-schema.org/draft-03/schema#" => Some(SpecVersion::Draft03),
61 "http://json-schema.org/draft-04/schema#" | "http://json-schema.org/schema#" => {
62 Some(SpecVersion::Draft04)
63 } "http://json-schema.org/draft-05/schema#" => Some(SpecVersion::Draft05),
65 "http://json-schema.org/draft-06/schema#" => Some(SpecVersion::Draft06),
66 "http://json-schema.org/draft-07/schema#" => Some(SpecVersion::Draft07),
67 "https://json-schema.org/draft/2019-09/schema" => Some(SpecVersion::Draft201909),
68 "https://json-schema.org/draft/2020-12/schema" => Some(SpecVersion::Draft202012),
69 _ => None,
70 }
71 }
72
73 #[must_use]
80 pub fn default_schema_settings(self) -> JsonSchemaSettings {
81 JsonSchemaSettings {
82 disallow_unknown_fields: false,
83 spec_version: None,
84 }
85 }
86}
87
88#[cfg(test)]
89mod tests {
90 use crate::json_schema::SpecVersion;
91 use crate::json_schema::settings::JsonSchemaSettings;
92
93 #[test]
94 fn spec_version_returns_settings() {
95 let settings: JsonSchemaSettings = SpecVersion::Draft07.default_schema_settings();
96 assert!(!settings.disallow_unknown_fields);
97 }
98
99 #[test]
101 fn default_settings_match_draft202012() {
102 let from_builder: JsonSchemaSettings = JsonSchemaSettings::default();
103 let from_spec: JsonSchemaSettings = SpecVersion::Draft202012.default_schema_settings();
104 assert_eq!(from_builder, from_spec);
105 }
106
107 #[test]
110 fn schema_uri_draft00() {
111 let expected: &str = "http://json-schema.org/draft-00/hyper-schema#";
112 let actual: &str = SpecVersion::Draft00.schema_uri();
113 assert_eq!(expected, actual);
114 }
115
116 #[test]
117 fn schema_uri_draft01() {
118 let expected: &str = "http://json-schema.org/draft-01/hyper-schema#";
119 let actual: &str = SpecVersion::Draft01.schema_uri();
120 assert_eq!(expected, actual);
121 }
122
123 #[test]
124 fn schema_uri_draft02() {
125 let expected: &str = "http://json-schema.org/draft-02/hyper-schema#";
126 let actual: &str = SpecVersion::Draft02.schema_uri();
127 assert_eq!(expected, actual);
128 }
129
130 #[test]
131 fn schema_uri_draft03() {
132 let expected: &str = "http://json-schema.org/draft-03/schema#";
133 let actual: &str = SpecVersion::Draft03.schema_uri();
134 assert_eq!(expected, actual);
135 }
136
137 #[test]
138 fn schema_uri_draft04() {
139 let expected: &str = "http://json-schema.org/draft-04/schema#";
140 let actual: &str = SpecVersion::Draft04.schema_uri();
141 assert_eq!(expected, actual);
142 }
143
144 #[test]
145 fn schema_uri_draft05() {
146 let expected: &str = "http://json-schema.org/draft-05/schema#";
147 let actual: &str = SpecVersion::Draft05.schema_uri();
148 assert_eq!(expected, actual);
149 }
150
151 #[test]
152 fn schema_uri_draft06() {
153 let expected: &str = "http://json-schema.org/draft-06/schema#";
154 let actual: &str = SpecVersion::Draft06.schema_uri();
155 assert_eq!(expected, actual);
156 }
157
158 #[test]
159 fn schema_uri_draft07() {
160 let expected: &str = "http://json-schema.org/draft-07/schema#";
161 let actual: &str = SpecVersion::Draft07.schema_uri();
162 assert_eq!(expected, actual);
163 }
164
165 #[test]
166 fn schema_uri_draft201909() {
167 let expected: &str = "https://json-schema.org/draft/2019-09/schema";
168 let actual: &str = SpecVersion::Draft201909.schema_uri();
169 assert_eq!(expected, actual);
170 }
171
172 #[test]
173 fn schema_uri_draft202012() {
174 let expected: &str = "https://json-schema.org/draft/2020-12/schema";
175 let actual: &str = SpecVersion::Draft202012.schema_uri();
176 assert_eq!(expected, actual);
177 }
178
179 #[test]
182 fn from_schema_uri_round_trip_draft00() {
183 let v: SpecVersion = SpecVersion::Draft00;
184 let expected: Option<SpecVersion> = Some(v);
185 let actual: Option<SpecVersion> = SpecVersion::from_schema_uri(v.schema_uri());
186 assert_eq!(expected, actual);
187 }
188
189 #[test]
190 fn from_schema_uri_round_trip_draft01() {
191 let v: SpecVersion = SpecVersion::Draft01;
192 let expected: Option<SpecVersion> = Some(v);
193 let actual: Option<SpecVersion> = SpecVersion::from_schema_uri(v.schema_uri());
194 assert_eq!(expected, actual);
195 }
196
197 #[test]
198 fn from_schema_uri_round_trip_draft02() {
199 let v: SpecVersion = SpecVersion::Draft02;
200 let expected: Option<SpecVersion> = Some(v);
201 let actual: Option<SpecVersion> = SpecVersion::from_schema_uri(v.schema_uri());
202 assert_eq!(expected, actual);
203 }
204
205 #[test]
206 fn from_schema_uri_round_trip_draft03() {
207 let v: SpecVersion = SpecVersion::Draft03;
208 let expected: Option<SpecVersion> = Some(v);
209 let actual: Option<SpecVersion> = SpecVersion::from_schema_uri(v.schema_uri());
210 assert_eq!(expected, actual);
211 }
212
213 #[test]
214 fn from_schema_uri_round_trip_draft04() {
215 let v: SpecVersion = SpecVersion::Draft04;
216 let expected: Option<SpecVersion> = Some(v);
217 let actual: Option<SpecVersion> = SpecVersion::from_schema_uri(v.schema_uri());
218 assert_eq!(expected, actual);
219 }
220
221 #[test]
222 fn from_schema_uri_round_trip_draft05() {
223 let v: SpecVersion = SpecVersion::Draft05;
224 let expected: Option<SpecVersion> = Some(v);
225 let actual: Option<SpecVersion> = SpecVersion::from_schema_uri(v.schema_uri());
226 assert_eq!(expected, actual);
227 }
228
229 #[test]
230 fn from_schema_uri_round_trip_draft06() {
231 let v: SpecVersion = SpecVersion::Draft06;
232 let expected: Option<SpecVersion> = Some(v);
233 let actual: Option<SpecVersion> = SpecVersion::from_schema_uri(v.schema_uri());
234 assert_eq!(expected, actual);
235 }
236
237 #[test]
238 fn from_schema_uri_round_trip_draft07() {
239 let v: SpecVersion = SpecVersion::Draft07;
240 let expected: Option<SpecVersion> = Some(v);
241 let actual: Option<SpecVersion> = SpecVersion::from_schema_uri(v.schema_uri());
242 assert_eq!(expected, actual);
243 }
244
245 #[test]
246 fn from_schema_uri_round_trip_draft201909() {
247 let v: SpecVersion = SpecVersion::Draft201909;
248 let expected: Option<SpecVersion> = Some(v);
249 let actual: Option<SpecVersion> = SpecVersion::from_schema_uri(v.schema_uri());
250 assert_eq!(expected, actual);
251 }
252
253 #[test]
254 fn from_schema_uri_round_trip_draft202012() {
255 let v: SpecVersion = SpecVersion::Draft202012;
256 let expected: Option<SpecVersion> = Some(v);
257 let actual: Option<SpecVersion> = SpecVersion::from_schema_uri(v.schema_uri());
258 assert_eq!(expected, actual);
259 }
260
261 #[test]
264 fn from_schema_uri_canonical_2020_12() {
265 let expected: Option<SpecVersion> = Some(SpecVersion::Draft202012);
266 let actual: Option<SpecVersion> =
267 SpecVersion::from_schema_uri("https://json-schema.org/draft/2020-12/schema");
268 assert_eq!(expected, actual);
269 }
270
271 #[test]
272 fn from_schema_uri_canonical_2019_09() {
273 let expected: Option<SpecVersion> = Some(SpecVersion::Draft201909);
274 let actual: Option<SpecVersion> =
275 SpecVersion::from_schema_uri("https://json-schema.org/draft/2019-09/schema");
276 assert_eq!(expected, actual);
277 }
278
279 #[test]
280 fn from_schema_uri_canonical_draft07() {
281 let expected: Option<SpecVersion> = Some(SpecVersion::Draft07);
282 let actual: Option<SpecVersion> =
283 SpecVersion::from_schema_uri("http://json-schema.org/draft-07/schema#");
284 assert_eq!(expected, actual);
285 }
286
287 #[test]
288 fn from_schema_uri_canonical_draft04() {
289 let expected: Option<SpecVersion> = Some(SpecVersion::Draft04);
290 let actual: Option<SpecVersion> =
291 SpecVersion::from_schema_uri("http://json-schema.org/draft-04/schema#");
292 assert_eq!(expected, actual);
293 }
294
295 #[test]
296 fn from_schema_uri_legacy_draft04_schema_hash() {
297 let expected: Option<SpecVersion> = Some(SpecVersion::Draft04);
298 let actual: Option<SpecVersion> =
299 SpecVersion::from_schema_uri("http://json-schema.org/schema#");
300 assert_eq!(expected, actual);
301 }
302
303 #[test]
306 fn from_schema_uri_empty_returns_none() {
307 let expected: Option<SpecVersion> = None;
308 let actual: Option<SpecVersion> = SpecVersion::from_schema_uri("");
309 assert_eq!(expected, actual);
310 }
311
312 #[test]
313 fn from_schema_uri_whitespace_only_returns_none() {
314 let expected: Option<SpecVersion> = None;
315 let actual: Option<SpecVersion> = SpecVersion::from_schema_uri(" ");
316 assert_eq!(expected, actual);
317 }
318
319 #[test]
320 fn from_schema_uri_unknown_returns_none() {
321 let expected: Option<SpecVersion> = None;
322 let actual: Option<SpecVersion> =
323 SpecVersion::from_schema_uri("https://unknown.example.com/schema");
324 assert_eq!(expected, actual);
325 }
326
327 #[test]
328 fn from_schema_uri_malformed_returns_none() {
329 let expected: Option<SpecVersion> = None;
330 let actual: Option<SpecVersion> = SpecVersion::from_schema_uri("not-a-uri");
331 assert_eq!(expected, actual);
332 }
333
334 #[test]
335 fn from_schema_uri_trailing_slash_normalized() {
336 let expected: Option<SpecVersion> = Some(SpecVersion::Draft202012);
342 let actual: Option<SpecVersion> =
343 SpecVersion::from_schema_uri("https://json-schema.org/draft/2020-12/schema/");
344 assert_eq!(expected, actual);
345 }
346}