Skip to content

Commit 6953a4a

Browse files
committed
support const keyword
1 parent 7dc0458 commit 6953a4a

25 files changed

+338
-19
lines changed

src/diff_walker.rs

Lines changed: 62 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
use std::collections::BTreeSet;
1+
use std::collections::{BTreeMap, BTreeSet};
22

33
use schemars::schema::{
4-
InstanceType, NumberValidation, RootSchema, Schema, SchemaObject, SingleOrVec,
5-
SubschemaValidation,
4+
InstanceType, NumberValidation, ObjectValidation, RootSchema, Schema, SchemaObject,
5+
SingleOrVec, SubschemaValidation,
66
};
77
use serde_json::Value;
88

@@ -77,6 +77,37 @@ impl DiffWalker {
7777
}
7878
}
7979

80+
fn diff_const(&mut self, json_path: &str, lhs: &mut SchemaObject, rhs: &mut SchemaObject) {
81+
Self::normalize_const(lhs);
82+
Self::normalize_const(rhs);
83+
match (&lhs.const_value, &rhs.const_value) {
84+
(Some(value), None) => self.changes.push(Change {
85+
path: json_path.to_owned(),
86+
change: ChangeKind::ConstRemove {
87+
removed: value.clone(),
88+
},
89+
}),
90+
(None, Some(value)) => self.changes.push(Change {
91+
path: json_path.to_owned(),
92+
change: ChangeKind::ConstAdd {
93+
added: value.clone(),
94+
},
95+
}),
96+
(Some(l), Some(r)) if l != r => {
97+
if l.is_object() && r.is_object() {}
98+
self.changes.push(Change {
99+
path: json_path.to_owned(),
100+
change: ChangeKind::ConstRemove { removed: l.clone() },
101+
});
102+
self.changes.push(Change {
103+
path: json_path.to_owned(),
104+
change: ChangeKind::ConstAdd { added: r.clone() },
105+
});
106+
}
107+
_ => (),
108+
}
109+
}
110+
80111
fn diff_properties(
81112
&mut self,
82113
json_path: &str,
@@ -384,6 +415,33 @@ impl DiffWalker {
384415
(schema_object, is_split)
385416
}
386417

418+
fn normalize_const(schema_object: &mut SchemaObject) {
419+
fn do_normalize(value: Value) -> SchemaObject {
420+
match value {
421+
Value::Object(obj) => {
422+
let properties = obj
423+
.into_iter()
424+
.map(|(k, v)| (k, Schema::Object(do_normalize(v))))
425+
.collect::<BTreeMap<_, _>>();
426+
SchemaObject {
427+
object: Some(Box::new(ObjectValidation {
428+
properties,
429+
..Default::default()
430+
})),
431+
..Default::default()
432+
}
433+
}
434+
_ => SchemaObject {
435+
const_value: Some(value),
436+
..Default::default()
437+
},
438+
}
439+
}
440+
if let Some(value) = schema_object.const_value.take() {
441+
*schema_object = do_normalize(value)
442+
}
443+
}
444+
387445
fn do_diff(
388446
&mut self,
389447
json_path: &str,
@@ -399,6 +457,7 @@ impl DiffWalker {
399457
if !comparing_any_of {
400458
self.diff_instance_types(json_path, lhs, rhs);
401459
}
460+
self.diff_const(json_path, lhs, rhs);
402461
// If we split the types, we don't want to compare type-specific properties
403462
// because they are already compared in the `Self::diff_any_of`
404463
if !is_lhs_split && !is_rhs_split {

src/types.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,16 @@ pub enum ChangeKind {
2626
/// The type in question.
2727
removed: JsonSchemaType,
2828
},
29+
/// A const value has been added as an allowed value.
30+
ConstAdd {
31+
/// The value of the added const.
32+
added: serde_json::Value,
33+
},
34+
/// A const has been removed as an allowed value.
35+
ConstRemove {
36+
/// The value of the removed const.
37+
removed: serde_json::Value,
38+
},
2939
/// A property has been added and (depending on additionalProperties) is now additionally
3040
/// allowed.
3141
PropertyAdd {
@@ -117,6 +127,8 @@ impl ChangeKind {
117127
match self {
118128
Self::TypeAdd { .. } => false,
119129
Self::TypeRemove { .. } => true,
130+
Self::ConstAdd { .. } => true,
131+
Self::ConstRemove { .. } => false,
120132
Self::PropertyAdd {
121133
lhs_additional_properties,
122134
..
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"lhs": { "anyOf": [{ "type": "number" }, { "type": "string" }] },
3+
"rhs": { "anyOf": [{ "const": 1 }, { "const": "1" }] }
4+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"lhs": { "anyOf": [{ "type": "number" }, { "type": "string" }, { "const": 1 }] },
3+
"rhs": { "anyOf": [{ "const": 1 }, { "const": "1" }] }
4+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"lhs": { "anyOf": [{ "type": "object" }, { "type": "string" }, { "const": { "key": "value" } }] },
3+
"rhs": { "anyOf": [{ "properties": { "key": { "const": "value" } } }, { "const": "1" }] }
4+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"lhs": { "const": { "key": "value" } },
3+
"rhs": { "properties": { "key": { "const": "value" } } }
4+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"lhs": { "const": "foo" },
3+
"rhs": { "const": 1 }
4+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"lhs": { "const": "foo" },
3+
"rhs": { "const": "bar" }
4+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"lhs": { "type": "integer" },
3+
"rhs": { "const": "foo" }
4+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"lhs": { "type": "number" },
3+
"rhs": { "const": "foo" }
4+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"lhs": { "type": "object" },
3+
"rhs": { "const": { "key": "value" } }
4+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"lhs": { "type": "string" },
3+
"rhs": { "const": 1 }
4+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
---
2+
source: tests/test.rs
3+
expression: diff
4+
input_file: tests/fixtures/const/const_in_any_of_1.json
5+
---
6+
[
7+
Change {
8+
path: ".<anyOf:0>",
9+
change: ConstAdd {
10+
added: Number(1),
11+
},
12+
},
13+
Change {
14+
path: ".<anyOf:1>",
15+
change: ConstAdd {
16+
added: String("1"),
17+
},
18+
},
19+
]
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
---
2+
source: tests/test.rs
3+
expression: diff
4+
input_file: tests/fixtures/const/const_in_any_of_2.json
5+
---
6+
[
7+
Change {
8+
path: ".<anyOf:1>",
9+
change: ConstAdd {
10+
added: String("1"),
11+
},
12+
},
13+
]
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
---
2+
source: tests/test.rs
3+
expression: diff
4+
input_file: tests/fixtures/const/const_in_any_of_3.json
5+
---
6+
[
7+
Change {
8+
path: ".<anyOf:1>",
9+
change: ConstAdd {
10+
added: String("1"),
11+
},
12+
},
13+
]
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
source: tests/test.rs
3+
expression: diff
4+
input_file: tests/fixtures/const/const_in_properties.json
5+
---
6+
[]
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
---
2+
source: tests/test.rs
3+
expression: diff
4+
input_file: tests/fixtures/const/const_string_to_const_number.json
5+
---
6+
[
7+
Change {
8+
path: "",
9+
change: TypeRemove {
10+
removed: String,
11+
},
12+
},
13+
Change {
14+
path: "",
15+
change: TypeAdd {
16+
added: Number,
17+
},
18+
},
19+
Change {
20+
path: "",
21+
change: TypeAdd {
22+
added: Integer,
23+
},
24+
},
25+
Change {
26+
path: "",
27+
change: ConstRemove {
28+
removed: String("foo"),
29+
},
30+
},
31+
Change {
32+
path: "",
33+
change: ConstAdd {
34+
added: Number(1),
35+
},
36+
},
37+
]
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
---
2+
source: tests/test.rs
3+
expression: diff
4+
input_file: tests/fixtures/const/const_string_to_other_const_string.json
5+
---
6+
[
7+
Change {
8+
path: "",
9+
change: ConstRemove {
10+
removed: String("foo"),
11+
},
12+
},
13+
Change {
14+
path: "",
15+
change: ConstAdd {
16+
added: String("bar"),
17+
},
18+
},
19+
]
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
---
2+
source: tests/test.rs
3+
expression: diff
4+
input_file: tests/fixtures/const/integer_to_const_string.json
5+
---
6+
[
7+
Change {
8+
path: "",
9+
change: TypeRemove {
10+
removed: Integer,
11+
},
12+
},
13+
Change {
14+
path: "",
15+
change: TypeAdd {
16+
added: String,
17+
},
18+
},
19+
Change {
20+
path: "",
21+
change: ConstAdd {
22+
added: String("foo"),
23+
},
24+
},
25+
]
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
---
2+
source: tests/test.rs
3+
expression: diff
4+
input_file: tests/fixtures/const/number_to_const_string.json
5+
---
6+
[
7+
Change {
8+
path: "",
9+
change: TypeRemove {
10+
removed: Number,
11+
},
12+
},
13+
Change {
14+
path: "",
15+
change: TypeRemove {
16+
removed: Integer,
17+
},
18+
},
19+
Change {
20+
path: "",
21+
change: TypeAdd {
22+
added: String,
23+
},
24+
},
25+
Change {
26+
path: "",
27+
change: ConstAdd {
28+
added: String("foo"),
29+
},
30+
},
31+
]
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
---
2+
source: tests/test.rs
3+
expression: diff
4+
input_file: tests/fixtures/const/object_to_const_object.json
5+
---
6+
[
7+
Change {
8+
path: "",
9+
change: PropertyAdd {
10+
lhs_additional_properties: true,
11+
added: "key",
12+
},
13+
},
14+
]
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
---
2+
source: tests/test.rs
3+
expression: diff
4+
input_file: tests/fixtures/const/string_to_const_number.json
5+
---
6+
[
7+
Change {
8+
path: "",
9+
change: TypeRemove {
10+
removed: String,
11+
},
12+
},
13+
Change {
14+
path: "",
15+
change: TypeAdd {
16+
added: Number,
17+
},
18+
},
19+
Change {
20+
path: "",
21+
change: TypeAdd {
22+
added: Integer,
23+
},
24+
},
25+
Change {
26+
path: "",
27+
change: ConstAdd {
28+
added: Number(1),
29+
},
30+
},
31+
]

0 commit comments

Comments
 (0)