jsonschema_rs 0.49.1 → 0.49.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +64 -1
- data/Cargo.toml +2 -2
- data/ext/jsonschema/Cargo.lock +13 -13
- data/ext/jsonschema/Cargo.toml +3 -3
- data/lib/jsonschema/version.rb +1 -1
- data/sig/jsonschema.rbs +10 -0
- data/src/canonical.rs +227 -2
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1f9c13c1388f5e57ffff9783a04a15144954e15c0078414321bb7f699a7ebe6a
|
|
4
|
+
data.tar.gz: 866810b923d5654fc09def7495882a7e82bed9ac248594304885df21a9fb2699
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 31bb5ae7145e6dec76c88ad04e38f354abd7cb8853df576e260503d783c324da7cdd921e5472a647354247cd8b370fa79c6ea1c8e653164349b35f13f8ef81e4
|
|
7
|
+
data.tar.gz: ea2c1a7ec8afed706a4d05504b3f69e58c2ee574b373b64eb828ff1f6c2b977b539bbe4aa45966250e4ea6bab234f9e86cfbd974b72d34c4bc3738f94c3836cd
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,66 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.49.4] - 2026-08-04
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Canonicalization of `not` a string format, which the string leaf carries as barred formats.
|
|
10
|
+
- Canonicalization of `not` an existential demand, which an array fails exactly when no element matches.
|
|
11
|
+
- Canonicalization of `not` a string value set, which the string leaf carries as excluded values.
|
|
12
|
+
- Canonicalization of `unevaluatedItems` beside `contains`, where the elements it matches are evaluated and the tail admits either.
|
|
13
|
+
- Canonicalization of `unevaluated*` beside `anyOf` or `oneOf`, where every branch evaluating the same keys or indexes pins what is left over.
|
|
14
|
+
- Canonicalization of `not` an array element schema, which an array fails exactly when one element violates it.
|
|
15
|
+
- `CanonicalSchema#intersect`, the values both schemas admit.
|
|
16
|
+
- `CanonicalSchema#negate`, the values a schema rejects.
|
|
17
|
+
- `CanonicalSchema#definition`, one reference target by URI.
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
|
|
21
|
+
- An integer past `i64` admitted by a fractional bound `f64` rounds it onto, such as `-10000000000000000000000000` under `{"maximum": -10000000000000000000000000.1}`.
|
|
22
|
+
- An integer past `2^53` admitted by a bound `f64` rounds onto it, such as `9007199254740992` under `{"minimum": 9007199254740993}`.
|
|
23
|
+
- A `contains` subschema beside both `minContains` and `maxContains` overwriting a sibling keyword of the same name, such as `items`.
|
|
24
|
+
|
|
25
|
+
### Performance
|
|
26
|
+
|
|
27
|
+
- `CanonicalSchema` hashing and equality cost the node instead of the whole document.
|
|
28
|
+
|
|
29
|
+
## [0.49.3] - 2026-08-02
|
|
30
|
+
|
|
31
|
+
### Added
|
|
32
|
+
|
|
33
|
+
- Canonicalization of a recursive schema with no finite witness, which now folds to `false`.
|
|
34
|
+
- Canonicalization of `$dynamicRef` and `$recursiveRef`, which resolve through the dynamic scope and stay symbolic like any other reference. A dangling `$dynamicRef` errors rather than staying `Raw`.
|
|
35
|
+
- Canonicalization of `minContains` under `uniqueItems`, where a demand asking for more matches than its own schema has distinct values now folds to `false`.
|
|
36
|
+
- Canonicalization of a Draft 4 `patternProperties` coverage closed by `additionalProperties: false`, spelled as the closed map it was parsed from.
|
|
37
|
+
- Canonicalization of a `oneOf` whose branches repeat, where a repeated branch can never contribute exactly one match.
|
|
38
|
+
- Canonicalization of a `$ref` whose target is an empty schema, which now folds to `false`.
|
|
39
|
+
- Canonicalization of `unevaluatedItems` beside `allOf`, where every branch must pass and so the indexes they evaluate are known without the instance.
|
|
40
|
+
- Canonicalization of `unevaluatedProperties` beside `allOf`, where every branch must pass and so what they evaluate is known without the instance.
|
|
41
|
+
- Canonicalization of a Draft 4 `type` list holding `integer` beside other types with `enum`, which previously modeled only when spelled as an `allOf`.
|
|
42
|
+
- Canonicalization of `patternProperties` patterns matching finitely many keys, such as `^a$` and `^(a|b)$`.
|
|
43
|
+
- Canonicalization of `unevaluatedProperties` and `unevaluatedItems` when no in-place applicator sits beside them.
|
|
44
|
+
|
|
45
|
+
### Fixed
|
|
46
|
+
|
|
47
|
+
- `additionalItems` values that are not schemas silently ignored beside an array-form `items` (they should fail the build like `additionalProperties`).
|
|
48
|
+
- `additionalItems` beside a boolean `items` rejecting every instance, such as `{"additionalItems": false, "items": false}`.
|
|
49
|
+
- Draft 4 rejecting a size bound at or past `2^64`, such as `{"maxItems": 18446744073709551616}`.
|
|
50
|
+
- An integer past the `f64` range admitted by a fractional bound it exceeds, such as `1e400` under `{"exclusiveMaximum": 0.1}`.
|
|
51
|
+
- A `$ref` at the root of an `$id`-bearing subresource dropped as a self-reference when its pointer matched the one that reached that subresource.
|
|
52
|
+
- Canonicalization reusing one definition's body for a same-named definition in another resource, when the name spells a canonical URI.
|
|
53
|
+
- `unevaluatedItems` counting `prefixItems` as evaluating elements before Draft 2020-12, where it is not a keyword.
|
|
54
|
+
|
|
55
|
+
### Performance
|
|
56
|
+
|
|
57
|
+
- Up to 70% faster `evaluate`.
|
|
58
|
+
|
|
59
|
+
## [0.49.2] - 2026-07-28
|
|
60
|
+
|
|
61
|
+
### Performance
|
|
62
|
+
|
|
63
|
+
- Faster serialization of canonicalized schemas.
|
|
64
|
+
|
|
5
65
|
## [0.49.1] - 2026-07-25
|
|
6
66
|
|
|
7
67
|
### Fixed
|
|
@@ -226,7 +286,10 @@
|
|
|
226
286
|
|
|
227
287
|
- Initial public release
|
|
228
288
|
|
|
229
|
-
[Unreleased]: https://github.com/Stranger6667/jsonschema/compare/ruby-v0.49.
|
|
289
|
+
[Unreleased]: https://github.com/Stranger6667/jsonschema/compare/ruby-v0.49.4...HEAD
|
|
290
|
+
[0.49.4]: https://github.com/Stranger6667/jsonschema/compare/ruby-v0.49.3...ruby-v0.49.4
|
|
291
|
+
[0.49.3]: https://github.com/Stranger6667/jsonschema/compare/ruby-v0.49.2...ruby-v0.49.3
|
|
292
|
+
[0.49.2]: https://github.com/Stranger6667/jsonschema/compare/ruby-v0.49.1...ruby-v0.49.2
|
|
230
293
|
[0.49.1]: https://github.com/Stranger6667/jsonschema/compare/ruby-v0.49.0...ruby-v0.49.1
|
|
231
294
|
[0.49.0]: https://github.com/Stranger6667/jsonschema/compare/ruby-v0.48.5...ruby-v0.49.0
|
|
232
295
|
[0.48.5]: https://github.com/Stranger6667/jsonschema/compare/ruby-v0.48.2...ruby-v0.48.5
|
data/Cargo.toml
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "jsonschema-rb"
|
|
3
|
-
version = "0.49.
|
|
3
|
+
version = "0.49.4"
|
|
4
4
|
edition = "2021"
|
|
5
5
|
authors = ["Dmitry Dygalo <dmitry@dygalo.dev>"]
|
|
6
6
|
license = "MIT"
|
|
@@ -13,7 +13,7 @@ publish = false
|
|
|
13
13
|
crate-type = ["cdylib"]
|
|
14
14
|
|
|
15
15
|
[dependencies]
|
|
16
|
-
jsonschema = { version = "0.49.
|
|
16
|
+
jsonschema = { version = "0.49.4", default-features = false, features = ["magnus", "arbitrary-precision", "resolve-http", "resolve-file", "tls-ring", "macros"] }
|
|
17
17
|
magnus = { version = "0.8", features = ["rb-sys"] }
|
|
18
18
|
rb-sys = "0.9"
|
|
19
19
|
serde = { workspace = true }
|
data/ext/jsonschema/Cargo.lock
CHANGED
|
@@ -693,9 +693,9 @@ dependencies = [
|
|
|
693
693
|
|
|
694
694
|
[[package]]
|
|
695
695
|
name = "jsonschema"
|
|
696
|
-
version = "0.49.
|
|
696
|
+
version = "0.49.4"
|
|
697
697
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
698
|
-
checksum = "
|
|
698
|
+
checksum = "257549c093d8f3d043337ba0d507e8eeace2447dfae3f0ee37eb0f57d3df7655"
|
|
699
699
|
dependencies = [
|
|
700
700
|
"ahash",
|
|
701
701
|
"bytecount",
|
|
@@ -726,9 +726,9 @@ dependencies = [
|
|
|
726
726
|
|
|
727
727
|
[[package]]
|
|
728
728
|
name = "jsonschema-macros"
|
|
729
|
-
version = "0.49.
|
|
729
|
+
version = "0.49.4"
|
|
730
730
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
731
|
-
checksum = "
|
|
731
|
+
checksum = "b043434e5e987e02043a6fd8d0c2686c8db4fe31a37b373ef9b2a9b1f27b96c6"
|
|
732
732
|
dependencies = [
|
|
733
733
|
"jsonschema-macros-core",
|
|
734
734
|
"proc-macro2",
|
|
@@ -736,9 +736,9 @@ dependencies = [
|
|
|
736
736
|
|
|
737
737
|
[[package]]
|
|
738
738
|
name = "jsonschema-macros-core"
|
|
739
|
-
version = "0.49.
|
|
739
|
+
version = "0.49.4"
|
|
740
740
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
741
|
-
checksum = "
|
|
741
|
+
checksum = "892e0b0739e173cce25aef424366940b20eebe7dd29304a4b8484bbd1461cc8b"
|
|
742
742
|
dependencies = [
|
|
743
743
|
"fancy-regex",
|
|
744
744
|
"indexmap",
|
|
@@ -755,7 +755,7 @@ dependencies = [
|
|
|
755
755
|
|
|
756
756
|
[[package]]
|
|
757
757
|
name = "jsonschema-rb-ext"
|
|
758
|
-
version = "0.49.
|
|
758
|
+
version = "0.49.4"
|
|
759
759
|
dependencies = [
|
|
760
760
|
"jsonschema",
|
|
761
761
|
"magnus",
|
|
@@ -768,18 +768,18 @@ dependencies = [
|
|
|
768
768
|
|
|
769
769
|
[[package]]
|
|
770
770
|
name = "jsonschema-regex"
|
|
771
|
-
version = "0.49.
|
|
771
|
+
version = "0.49.4"
|
|
772
772
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
773
|
-
checksum = "
|
|
773
|
+
checksum = "474790e948498099d61ec85c10dc72d459d61298b7975eda7fb163af1934b134"
|
|
774
774
|
dependencies = [
|
|
775
775
|
"regex-syntax",
|
|
776
776
|
]
|
|
777
777
|
|
|
778
778
|
[[package]]
|
|
779
779
|
name = "jsonschema-value"
|
|
780
|
-
version = "0.49.
|
|
780
|
+
version = "0.49.4"
|
|
781
781
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
782
|
-
checksum = "
|
|
782
|
+
checksum = "8212315eb8e0bc44959d1af653cd5ec515771a3cdca966cfc0a10999bff144b9"
|
|
783
783
|
dependencies = [
|
|
784
784
|
"ahash",
|
|
785
785
|
"bytecount",
|
|
@@ -1132,9 +1132,9 @@ dependencies = [
|
|
|
1132
1132
|
|
|
1133
1133
|
[[package]]
|
|
1134
1134
|
name = "referencing"
|
|
1135
|
-
version = "0.49.
|
|
1135
|
+
version = "0.49.4"
|
|
1136
1136
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1137
|
-
checksum = "
|
|
1137
|
+
checksum = "2bf1a74e036be2546c0c81cdfad6b2def6a25bf31c4e34a468037058d3bd05c6"
|
|
1138
1138
|
dependencies = [
|
|
1139
1139
|
"ahash",
|
|
1140
1140
|
"fluent-uri",
|
data/ext/jsonschema/Cargo.toml
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "jsonschema-rb-ext"
|
|
3
|
-
version = "0.49.
|
|
3
|
+
version = "0.49.4"
|
|
4
4
|
edition = "2021"
|
|
5
5
|
publish = false
|
|
6
6
|
|
|
@@ -10,10 +10,10 @@ name = "jsonschema_rb"
|
|
|
10
10
|
path = "../../src/lib.rs"
|
|
11
11
|
|
|
12
12
|
[dependencies]
|
|
13
|
-
jsonschema = { version = "0.49.
|
|
13
|
+
jsonschema = { version = "0.49.4", default-features = false, features = ["magnus", "arbitrary-precision", "resolve-http", "resolve-file", "tls-ring", "macros"] }
|
|
14
14
|
magnus = { version = "0.8", features = ["rb-sys"] }
|
|
15
15
|
rb-sys = "0.9"
|
|
16
|
-
referencing = "0.49.
|
|
16
|
+
referencing = "0.49.4"
|
|
17
17
|
serde = { version = "1", features = ["derive"] }
|
|
18
18
|
serde_json = { version = "1", features = ["arbitrary_precision"] }
|
|
19
19
|
zmij = "1"
|
data/lib/jsonschema/version.rb
CHANGED
data/sig/jsonschema.rbs
CHANGED
|
@@ -32,12 +32,21 @@ module JSONSchema
|
|
|
32
32
|
class InvalidPattern < CanonicalizationError
|
|
33
33
|
end
|
|
34
34
|
|
|
35
|
+
class IncompatibleOperands < CanonicalizationError
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
class UnmodeledOperand < CanonicalizationError
|
|
39
|
+
end
|
|
40
|
+
|
|
35
41
|
# A schema reduced to canonical form: schemas accepting the same values share one form.
|
|
36
42
|
class CanonicalSchema
|
|
37
43
|
def to_json_schema: () -> untyped
|
|
38
44
|
def draft: () -> JSONSchema::draft
|
|
39
45
|
def kind: () -> kind
|
|
40
46
|
def view: () -> view
|
|
47
|
+
def intersect: (CanonicalSchema other) -> CanonicalSchema
|
|
48
|
+
def negate: () -> CanonicalSchema?
|
|
49
|
+
def definition: (String uri) -> CanonicalSchema?
|
|
41
50
|
def definitions: () -> Hash[String, CanonicalSchema]
|
|
42
51
|
def satisfiable?: () -> bool
|
|
43
52
|
def inspect: () -> String
|
|
@@ -77,6 +86,7 @@ module JSONSchema
|
|
|
77
86
|
def formats: () -> Array[String]
|
|
78
87
|
def content_media_types: () -> Array[String]
|
|
79
88
|
def content_encodings: () -> Array[String]
|
|
89
|
+
def excluded: () -> Array[String]
|
|
80
90
|
def inspect: () -> String
|
|
81
91
|
def deconstruct_keys: (untyped keys) -> Hash[Symbol, untyped]
|
|
82
92
|
end
|
data/src/canonical.rs
CHANGED
|
@@ -47,6 +47,8 @@ macro_rules! canonical_error_class {
|
|
|
47
47
|
canonical_error_class!(CANONICALIZATION_ERROR_CLASS, "CanonicalizationError");
|
|
48
48
|
canonical_error_class!(INVALID_SCHEMA_TYPE_CLASS, "InvalidSchemaType");
|
|
49
49
|
canonical_error_class!(INVALID_PATTERN_CLASS, "InvalidPattern");
|
|
50
|
+
canonical_error_class!(INCOMPATIBLE_OPERANDS_CLASS, "IncompatibleOperands");
|
|
51
|
+
canonical_error_class!(UNMODELED_OPERAND_CLASS, "UnmodeledOperand");
|
|
50
52
|
|
|
51
53
|
fn canonicalization_error(ruby: &Ruby, error: CanonicalizationError) -> Error {
|
|
52
54
|
if let CanonicalizationError::ValidationError(validation_error) = error {
|
|
@@ -60,6 +62,12 @@ fn canonicalization_error(ruby: &Ruby, error: CanonicalizationError) -> Error {
|
|
|
60
62
|
CanonicalizationError::InvalidPattern { .. } => {
|
|
61
63
|
Error::new(ruby.get_inner(&INVALID_PATTERN_CLASS), message)
|
|
62
64
|
}
|
|
65
|
+
CanonicalizationError::IncompatibleOperands(_) => {
|
|
66
|
+
Error::new(ruby.get_inner(&INCOMPATIBLE_OPERANDS_CLASS), message)
|
|
67
|
+
}
|
|
68
|
+
CanonicalizationError::UnmodeledOperand => {
|
|
69
|
+
Error::new(ruby.get_inner(&UNMODELED_OPERAND_CLASS), message)
|
|
70
|
+
}
|
|
63
71
|
// `ValidationError` returns above; future variants fall back to the base canonical error.
|
|
64
72
|
_ => Error::new(ruby.get_inner(&CANONICALIZATION_ERROR_CLASS), message),
|
|
65
73
|
}
|
|
@@ -141,8 +149,10 @@ impl RbCanonicalSchema {
|
|
|
141
149
|
max_length: view.max_length,
|
|
142
150
|
patterns: view.patterns,
|
|
143
151
|
formats: view.formats,
|
|
152
|
+
excluded_formats: view.excluded_formats,
|
|
144
153
|
content_media_types: view.content_media_types,
|
|
145
154
|
content_encodings: view.content_encodings,
|
|
155
|
+
excluded: view.excluded,
|
|
146
156
|
})
|
|
147
157
|
.as_value(),
|
|
148
158
|
CanonicalView::Number(view) => ruby
|
|
@@ -182,11 +192,38 @@ impl RbCanonicalSchema {
|
|
|
182
192
|
additional_properties: view.additional_properties,
|
|
183
193
|
})
|
|
184
194
|
.as_value(),
|
|
195
|
+
CanonicalView::Not(schema) => ruby.obj_wrap(NotView { schema: *schema }).as_value(),
|
|
196
|
+
CanonicalView::AllOf(branches) => ruby.obj_wrap(AllOfView { branches }).as_value(),
|
|
185
197
|
CanonicalView::AnyOf(branches) => ruby.obj_wrap(AnyOfView { branches }).as_value(),
|
|
198
|
+
CanonicalView::OneOf(branches) => ruby.obj_wrap(OneOfView { branches }).as_value(),
|
|
199
|
+
CanonicalView::Reference(uri) => ruby.obj_wrap(ReferenceView { uri }).as_value(),
|
|
186
200
|
CanonicalView::Raw(schema) => ruby.obj_wrap(RawView { schema }).as_value(),
|
|
187
201
|
}
|
|
188
202
|
}
|
|
189
203
|
|
|
204
|
+
fn intersect(ruby: &Ruby, rb_self: &Self, other: &Self) -> Result<Value, Error> {
|
|
205
|
+
rb_self
|
|
206
|
+
.inner
|
|
207
|
+
.intersect(&other.inner)
|
|
208
|
+
.map(|inner| ruby.obj_wrap(RbCanonicalSchema { inner }).as_value())
|
|
209
|
+
.map_err(|error| canonicalization_error(ruby, error))
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
fn negate(ruby: &Ruby, rb_self: &Self) -> Option<Value> {
|
|
213
|
+
rb_self
|
|
214
|
+
.inner
|
|
215
|
+
.negate()
|
|
216
|
+
.map(|inner| ruby.obj_wrap(RbCanonicalSchema { inner }).as_value())
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
#[allow(clippy::needless_pass_by_value)]
|
|
220
|
+
fn definition(ruby: &Ruby, rb_self: &Self, uri: String) -> Option<Value> {
|
|
221
|
+
rb_self
|
|
222
|
+
.inner
|
|
223
|
+
.definition(&uri)
|
|
224
|
+
.map(|inner| ruby.obj_wrap(RbCanonicalSchema { inner }).as_value())
|
|
225
|
+
}
|
|
226
|
+
|
|
190
227
|
fn definitions(ruby: &Ruby, rb_self: &Self) -> Result<RHash, Error> {
|
|
191
228
|
let hash = ruby.hash_new();
|
|
192
229
|
for (uri, target) in rb_self.inner.definitions() {
|
|
@@ -359,8 +396,10 @@ pub struct StringView {
|
|
|
359
396
|
max_length: Option<serde_json::Number>,
|
|
360
397
|
patterns: Vec<String>,
|
|
361
398
|
formats: Vec<String>,
|
|
399
|
+
excluded_formats: Vec<String>,
|
|
362
400
|
content_media_types: Vec<String>,
|
|
363
401
|
content_encodings: Vec<String>,
|
|
402
|
+
excluded: Vec<String>,
|
|
364
403
|
}
|
|
365
404
|
|
|
366
405
|
impl DataTypeFunctions for StringView {}
|
|
@@ -382,6 +421,10 @@ impl StringView {
|
|
|
382
421
|
strings_to_ruby(ruby, &rb_self.formats)
|
|
383
422
|
}
|
|
384
423
|
|
|
424
|
+
fn excluded_formats(ruby: &Ruby, rb_self: &Self) -> Result<Value, Error> {
|
|
425
|
+
strings_to_ruby(ruby, &rb_self.excluded_formats)
|
|
426
|
+
}
|
|
427
|
+
|
|
385
428
|
fn content_media_types(ruby: &Ruby, rb_self: &Self) -> Result<Value, Error> {
|
|
386
429
|
strings_to_ruby(ruby, &rb_self.content_media_types)
|
|
387
430
|
}
|
|
@@ -390,15 +433,21 @@ impl StringView {
|
|
|
390
433
|
strings_to_ruby(ruby, &rb_self.content_encodings)
|
|
391
434
|
}
|
|
392
435
|
|
|
436
|
+
fn excluded(ruby: &Ruby, rb_self: &Self) -> Result<Value, Error> {
|
|
437
|
+
strings_to_ruby(ruby, &rb_self.excluded)
|
|
438
|
+
}
|
|
439
|
+
|
|
393
440
|
fn inspect(ruby: &Ruby, rb_self: &Self) -> Result<String, Error> {
|
|
394
441
|
Ok(format!(
|
|
395
|
-
"#<JSONSchema::Canonical::StringView min_length={} max_length={} patterns={} formats={} content_media_types={} content_encodings={}>",
|
|
442
|
+
"#<JSONSchema::Canonical::StringView min_length={} max_length={} patterns={} formats={} excluded_formats={} content_media_types={} content_encodings={} excluded={}>",
|
|
396
443
|
Self::min_length(ruby, rb_self)?.inspect(),
|
|
397
444
|
Self::max_length(ruby, rb_self)?.inspect(),
|
|
398
445
|
Self::patterns(ruby, rb_self)?.inspect(),
|
|
399
446
|
Self::formats(ruby, rb_self)?.inspect(),
|
|
447
|
+
Self::excluded_formats(ruby, rb_self)?.inspect(),
|
|
400
448
|
Self::content_media_types(ruby, rb_self)?.inspect(),
|
|
401
|
-
Self::content_encodings(ruby, rb_self)?.inspect()
|
|
449
|
+
Self::content_encodings(ruby, rb_self)?.inspect(),
|
|
450
|
+
Self::excluded(ruby, rb_self)?.inspect()
|
|
402
451
|
))
|
|
403
452
|
}
|
|
404
453
|
|
|
@@ -408,6 +457,10 @@ impl StringView {
|
|
|
408
457
|
hash.aset(ruby.sym_new("max_length"), Self::max_length(ruby, rb_self)?)?;
|
|
409
458
|
hash.aset(ruby.sym_new("patterns"), Self::patterns(ruby, rb_self)?)?;
|
|
410
459
|
hash.aset(ruby.sym_new("formats"), Self::formats(ruby, rb_self)?)?;
|
|
460
|
+
hash.aset(
|
|
461
|
+
ruby.sym_new("excluded_formats"),
|
|
462
|
+
Self::excluded_formats(ruby, rb_self)?,
|
|
463
|
+
)?;
|
|
411
464
|
hash.aset(
|
|
412
465
|
ruby.sym_new("content_media_types"),
|
|
413
466
|
Self::content_media_types(ruby, rb_self)?,
|
|
@@ -416,6 +469,7 @@ impl StringView {
|
|
|
416
469
|
ruby.sym_new("content_encodings"),
|
|
417
470
|
Self::content_encodings(ruby, rb_self)?,
|
|
418
471
|
)?;
|
|
472
|
+
hash.aset(ruby.sym_new("excluded"), Self::excluded(ruby, rb_self)?)?;
|
|
419
473
|
Ok(hash)
|
|
420
474
|
}
|
|
421
475
|
}
|
|
@@ -836,6 +890,147 @@ impl AnyOfView {
|
|
|
836
890
|
}
|
|
837
891
|
}
|
|
838
892
|
|
|
893
|
+
/// A value matches iff exactly one branch matches.
|
|
894
|
+
#[derive(magnus::TypedData)]
|
|
895
|
+
#[magnus(class = "JSONSchema::Canonical::OneOfView", free_immediately)]
|
|
896
|
+
pub struct OneOfView {
|
|
897
|
+
branches: Vec<CanonicalSchema>,
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
impl DataTypeFunctions for OneOfView {}
|
|
901
|
+
|
|
902
|
+
impl OneOfView {
|
|
903
|
+
fn branches(ruby: &Ruby, rb_self: &Self) -> Result<Value, Error> {
|
|
904
|
+
let array = ruby.ary_new_capa(rb_self.branches.len());
|
|
905
|
+
for branch in &rb_self.branches {
|
|
906
|
+
array.push(
|
|
907
|
+
ruby.obj_wrap(RbCanonicalSchema {
|
|
908
|
+
inner: branch.clone(),
|
|
909
|
+
})
|
|
910
|
+
.as_value(),
|
|
911
|
+
)?;
|
|
912
|
+
}
|
|
913
|
+
Ok(array.as_value())
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
fn inspect(ruby: &Ruby, rb_self: &Self) -> Result<String, Error> {
|
|
917
|
+
let kinds = ruby.ary_new_capa(rb_self.branches.len());
|
|
918
|
+
for branch in &rb_self.branches {
|
|
919
|
+
kinds.push(ruby.sym_new(branch.kind().as_str()).as_value())?;
|
|
920
|
+
}
|
|
921
|
+
Ok(format!(
|
|
922
|
+
"#<JSONSchema::Canonical::OneOfView branches={}>",
|
|
923
|
+
kinds.as_value().inspect()
|
|
924
|
+
))
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
fn deconstruct_keys(ruby: &Ruby, rb_self: &Self, _keys: Value) -> Result<RHash, Error> {
|
|
928
|
+
let hash = ruby.hash_new();
|
|
929
|
+
hash.aset(ruby.sym_new("branches"), Self::branches(ruby, rb_self)?)?;
|
|
930
|
+
Ok(hash)
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
/// A value matches iff every branch matches.
|
|
935
|
+
#[derive(magnus::TypedData)]
|
|
936
|
+
#[magnus(class = "JSONSchema::Canonical::AllOfView", free_immediately)]
|
|
937
|
+
pub struct AllOfView {
|
|
938
|
+
branches: Vec<CanonicalSchema>,
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
impl DataTypeFunctions for AllOfView {}
|
|
942
|
+
|
|
943
|
+
impl AllOfView {
|
|
944
|
+
fn branches(ruby: &Ruby, rb_self: &Self) -> Result<Value, Error> {
|
|
945
|
+
let array = ruby.ary_new_capa(rb_self.branches.len());
|
|
946
|
+
for branch in &rb_self.branches {
|
|
947
|
+
array.push(
|
|
948
|
+
ruby.obj_wrap(RbCanonicalSchema {
|
|
949
|
+
inner: branch.clone(),
|
|
950
|
+
})
|
|
951
|
+
.as_value(),
|
|
952
|
+
)?;
|
|
953
|
+
}
|
|
954
|
+
Ok(array.as_value())
|
|
955
|
+
}
|
|
956
|
+
|
|
957
|
+
fn inspect(ruby: &Ruby, rb_self: &Self) -> Result<String, Error> {
|
|
958
|
+
let kinds = ruby.ary_new_capa(rb_self.branches.len());
|
|
959
|
+
for branch in &rb_self.branches {
|
|
960
|
+
kinds.push(ruby.sym_new(branch.kind().as_str()).as_value())?;
|
|
961
|
+
}
|
|
962
|
+
Ok(format!(
|
|
963
|
+
"#<JSONSchema::Canonical::AllOfView branches={}>",
|
|
964
|
+
kinds.as_value().inspect()
|
|
965
|
+
))
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
fn deconstruct_keys(ruby: &Ruby, rb_self: &Self, _keys: Value) -> Result<RHash, Error> {
|
|
969
|
+
let hash = ruby.hash_new();
|
|
970
|
+
hash.aset(ruby.sym_new("branches"), Self::branches(ruby, rb_self)?)?;
|
|
971
|
+
Ok(hash)
|
|
972
|
+
}
|
|
973
|
+
}
|
|
974
|
+
|
|
975
|
+
/// The complement of `schema`, preserving a symbolic ref under `not`, conditionals, and `oneOf`.
|
|
976
|
+
#[derive(magnus::TypedData)]
|
|
977
|
+
#[magnus(class = "JSONSchema::Canonical::NotView", free_immediately)]
|
|
978
|
+
pub struct NotView {
|
|
979
|
+
schema: CanonicalSchema,
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
impl DataTypeFunctions for NotView {}
|
|
983
|
+
|
|
984
|
+
impl NotView {
|
|
985
|
+
fn schema(ruby: &Ruby, rb_self: &Self) -> Value {
|
|
986
|
+
ruby.obj_wrap(RbCanonicalSchema {
|
|
987
|
+
inner: rb_self.schema.clone(),
|
|
988
|
+
})
|
|
989
|
+
.as_value()
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
fn inspect(rb_self: &Self) -> String {
|
|
993
|
+
format!(
|
|
994
|
+
"#<JSONSchema::Canonical::NotView schema={}>",
|
|
995
|
+
rb_self.schema.kind().as_str()
|
|
996
|
+
)
|
|
997
|
+
}
|
|
998
|
+
|
|
999
|
+
fn deconstruct_keys(ruby: &Ruby, rb_self: &Self, _keys: Value) -> Result<RHash, Error> {
|
|
1000
|
+
let hash = ruby.hash_new();
|
|
1001
|
+
hash.aset(ruby.sym_new("schema"), Self::schema(ruby, rb_self))?;
|
|
1002
|
+
Ok(hash)
|
|
1003
|
+
}
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
/// A symbolic JSON Schema reference.
|
|
1007
|
+
#[derive(magnus::TypedData)]
|
|
1008
|
+
#[magnus(class = "JSONSchema::Canonical::ReferenceView", free_immediately)]
|
|
1009
|
+
pub struct ReferenceView {
|
|
1010
|
+
uri: String,
|
|
1011
|
+
}
|
|
1012
|
+
|
|
1013
|
+
impl DataTypeFunctions for ReferenceView {}
|
|
1014
|
+
|
|
1015
|
+
impl ReferenceView {
|
|
1016
|
+
fn uri(rb_self: &Self) -> String {
|
|
1017
|
+
rb_self.uri.clone()
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
fn inspect(rb_self: &Self) -> String {
|
|
1021
|
+
format!(
|
|
1022
|
+
"#<JSONSchema::Canonical::ReferenceView uri={:?}>",
|
|
1023
|
+
rb_self.uri
|
|
1024
|
+
)
|
|
1025
|
+
}
|
|
1026
|
+
|
|
1027
|
+
fn deconstruct_keys(ruby: &Ruby, rb_self: &Self, _keys: Value) -> Result<RHash, Error> {
|
|
1028
|
+
let hash = ruby.hash_new();
|
|
1029
|
+
hash.aset(ruby.sym_new("uri"), rb_self.uri.clone())?;
|
|
1030
|
+
Ok(hash)
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
1033
|
+
|
|
839
1034
|
/// Exactly one admitted value.
|
|
840
1035
|
#[derive(magnus::TypedData)]
|
|
841
1036
|
#[magnus(class = "JSONSchema::Canonical::ConstView", free_immediately)]
|
|
@@ -938,6 +1133,8 @@ pub(crate) fn init_canonical(ruby: &Ruby, module: &RModule) -> Result<(), Error>
|
|
|
938
1133
|
canonical_module.define_error("CanonicalizationError", ruby.exception_standard_error())?;
|
|
939
1134
|
canonical_module.define_error("InvalidSchemaType", base_error)?;
|
|
940
1135
|
canonical_module.define_error("InvalidPattern", base_error)?;
|
|
1136
|
+
canonical_module.define_error("IncompatibleOperands", base_error)?;
|
|
1137
|
+
canonical_module.define_error("UnmodeledOperand", base_error)?;
|
|
941
1138
|
|
|
942
1139
|
let canonical_schema = canonical_module.define_class("CanonicalSchema", ruby.class_object())?;
|
|
943
1140
|
canonical_schema.define_method(
|
|
@@ -957,6 +1154,9 @@ pub(crate) fn init_canonical(ruby: &Ruby, module: &RModule) -> Result<(), Error>
|
|
|
957
1154
|
method!(<RbCanonicalSchema as typed_data::Hash>::hash, 0),
|
|
958
1155
|
)?;
|
|
959
1156
|
canonical_schema.define_method("view", method!(RbCanonicalSchema::view, 0))?;
|
|
1157
|
+
canonical_schema.define_method("intersect", method!(RbCanonicalSchema::intersect, 1))?;
|
|
1158
|
+
canonical_schema.define_method("negate", method!(RbCanonicalSchema::negate, 0))?;
|
|
1159
|
+
canonical_schema.define_method("definition", method!(RbCanonicalSchema::definition, 1))?;
|
|
960
1160
|
canonical_schema.define_method("definitions", method!(RbCanonicalSchema::definitions, 0))?;
|
|
961
1161
|
canonical_schema.define_method("satisfiable?", method!(RbCanonicalSchema::satisfiable, 0))?;
|
|
962
1162
|
|
|
@@ -997,6 +1197,7 @@ pub(crate) fn init_canonical(ruby: &Ruby, module: &RModule) -> Result<(), Error>
|
|
|
997
1197
|
string_view.define_method("max_length", method!(StringView::max_length, 0))?;
|
|
998
1198
|
string_view.define_method("patterns", method!(StringView::patterns, 0))?;
|
|
999
1199
|
string_view.define_method("formats", method!(StringView::formats, 0))?;
|
|
1200
|
+
string_view.define_method("excluded_formats", method!(StringView::excluded_formats, 0))?;
|
|
1000
1201
|
string_view.define_method(
|
|
1001
1202
|
"content_media_types",
|
|
1002
1203
|
method!(StringView::content_media_types, 0),
|
|
@@ -1005,6 +1206,7 @@ pub(crate) fn init_canonical(ruby: &Ruby, module: &RModule) -> Result<(), Error>
|
|
|
1005
1206
|
"content_encodings",
|
|
1006
1207
|
method!(StringView::content_encodings, 0),
|
|
1007
1208
|
)?;
|
|
1209
|
+
string_view.define_method("excluded", method!(StringView::excluded, 0))?;
|
|
1008
1210
|
string_view.define_method("inspect", method!(StringView::inspect, 0))?;
|
|
1009
1211
|
string_view.define_method("deconstruct_keys", method!(StringView::deconstruct_keys, 1))?;
|
|
1010
1212
|
|
|
@@ -1074,6 +1276,29 @@ pub(crate) fn init_canonical(ruby: &Ruby, module: &RModule) -> Result<(), Error>
|
|
|
1074
1276
|
any_of_view.define_method("inspect", method!(AnyOfView::inspect, 0))?;
|
|
1075
1277
|
any_of_view.define_method("deconstruct_keys", method!(AnyOfView::deconstruct_keys, 1))?;
|
|
1076
1278
|
|
|
1279
|
+
let one_of_view = canonical_module.define_class("OneOfView", ruby.class_object())?;
|
|
1280
|
+
one_of_view.define_method("branches", method!(OneOfView::branches, 0))?;
|
|
1281
|
+
one_of_view.define_method("inspect", method!(OneOfView::inspect, 0))?;
|
|
1282
|
+
one_of_view.define_method("deconstruct_keys", method!(OneOfView::deconstruct_keys, 1))?;
|
|
1283
|
+
|
|
1284
|
+
let all_of_view = canonical_module.define_class("AllOfView", ruby.class_object())?;
|
|
1285
|
+
all_of_view.define_method("branches", method!(AllOfView::branches, 0))?;
|
|
1286
|
+
all_of_view.define_method("inspect", method!(AllOfView::inspect, 0))?;
|
|
1287
|
+
all_of_view.define_method("deconstruct_keys", method!(AllOfView::deconstruct_keys, 1))?;
|
|
1288
|
+
|
|
1289
|
+
let not_view = canonical_module.define_class("NotView", ruby.class_object())?;
|
|
1290
|
+
not_view.define_method("schema", method!(NotView::schema, 0))?;
|
|
1291
|
+
not_view.define_method("inspect", method!(NotView::inspect, 0))?;
|
|
1292
|
+
not_view.define_method("deconstruct_keys", method!(NotView::deconstruct_keys, 1))?;
|
|
1293
|
+
|
|
1294
|
+
let reference_view = canonical_module.define_class("ReferenceView", ruby.class_object())?;
|
|
1295
|
+
reference_view.define_method("uri", method!(ReferenceView::uri, 0))?;
|
|
1296
|
+
reference_view.define_method("inspect", method!(ReferenceView::inspect, 0))?;
|
|
1297
|
+
reference_view.define_method(
|
|
1298
|
+
"deconstruct_keys",
|
|
1299
|
+
method!(ReferenceView::deconstruct_keys, 1),
|
|
1300
|
+
)?;
|
|
1301
|
+
|
|
1077
1302
|
let raw_view = canonical_module.define_class("RawView", ruby.class_object())?;
|
|
1078
1303
|
raw_view.define_method("schema", method!(RawView::schema, 0))?;
|
|
1079
1304
|
raw_view.define_method("inspect", method!(RawView::inspect, 0))?;
|