jsonschema_rs 0.48.2 → 0.48.5
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 +9 -1
- data/Cargo.toml +2 -2
- data/ext/jsonschema/Cargo.lock +27 -11
- data/ext/jsonschema/Cargo.toml +3 -3
- data/lib/jsonschema/version.rb +1 -1
- data/sig/jsonschema.rbs +102 -0
- data/src/canonical.rs +206 -27
- 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: 60ae1d2ffaa7543f17f5a7953a2ed92520f3887f7e92c8c8ac632f7c56e515ef
|
|
4
|
+
data.tar.gz: 8c3ac5d3f66016a881eed8a6f9f78327e32373e738ab453c39f0449365fce8a9
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3878552e31d235939c2fc5f4a7665002fa7ee604d4fed06a899ea78679b5ea76183322524b828376e5d891c154426a2fb1167604444eefcb8509afda8b477501
|
|
7
|
+
data.tar.gz: 9e6c6b67a2d3bea2ce93c31c1da0947832708ee55941950860ace90959ad4eb1d66c31e6a66273d17a3bd567f6fec739046c7b18deb6335e326cddfaab5fcdf1
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.48.5] - 2026-07-22
|
|
6
|
+
|
|
7
|
+
### Performance
|
|
8
|
+
|
|
9
|
+
- Avoid map lookups in some `properties` validators.
|
|
10
|
+
- Faster validation of `{"type": "array", "items": {...}}` schemas.
|
|
11
|
+
|
|
5
12
|
## [0.48.2] - 2026-07-21
|
|
6
13
|
|
|
7
14
|
### Fixed
|
|
@@ -192,7 +199,8 @@
|
|
|
192
199
|
|
|
193
200
|
- Initial public release
|
|
194
201
|
|
|
195
|
-
[Unreleased]: https://github.com/Stranger6667/jsonschema/compare/ruby-v0.48.
|
|
202
|
+
[Unreleased]: https://github.com/Stranger6667/jsonschema/compare/ruby-v0.48.5...HEAD
|
|
203
|
+
[0.48.5]: https://github.com/Stranger6667/jsonschema/compare/ruby-v0.48.2...ruby-v0.48.5
|
|
196
204
|
[0.48.2]: https://github.com/Stranger6667/jsonschema/compare/ruby-v0.48.1...ruby-v0.48.2
|
|
197
205
|
[0.48.1]: https://github.com/Stranger6667/jsonschema/compare/ruby-v0.48.0...ruby-v0.48.1
|
|
198
206
|
[0.48.0]: https://github.com/Stranger6667/jsonschema/compare/ruby-v0.47.0...ruby-v0.48.0
|
data/Cargo.toml
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "jsonschema-rb"
|
|
3
|
-
version = "0.48.
|
|
3
|
+
version = "0.48.5"
|
|
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.48.
|
|
16
|
+
jsonschema = { version = "0.48.5", default-features = false, features = ["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.48.
|
|
696
|
+
version = "0.48.5"
|
|
697
697
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
698
|
-
checksum = "
|
|
698
|
+
checksum = "f05a6cff806294a7699d48761d4ae2bdebab7fa2eef05e4a0b83320f0ff46901"
|
|
699
699
|
dependencies = [
|
|
700
700
|
"ahash",
|
|
701
701
|
"bytecount",
|
|
@@ -708,6 +708,7 @@ dependencies = [
|
|
|
708
708
|
"itoa",
|
|
709
709
|
"jsonschema-macros",
|
|
710
710
|
"jsonschema-regex",
|
|
711
|
+
"jsonschema-value",
|
|
711
712
|
"num-bigint",
|
|
712
713
|
"num-cmp",
|
|
713
714
|
"num-traits",
|
|
@@ -725,9 +726,9 @@ dependencies = [
|
|
|
725
726
|
|
|
726
727
|
[[package]]
|
|
727
728
|
name = "jsonschema-macros"
|
|
728
|
-
version = "0.48.
|
|
729
|
+
version = "0.48.5"
|
|
729
730
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
730
|
-
checksum = "
|
|
731
|
+
checksum = "40bda6e08b09b66cc0f70c0768118b51e8da7cef847036c88a68471b15101bcb"
|
|
731
732
|
dependencies = [
|
|
732
733
|
"jsonschema-macros-core",
|
|
733
734
|
"proc-macro2",
|
|
@@ -735,9 +736,9 @@ dependencies = [
|
|
|
735
736
|
|
|
736
737
|
[[package]]
|
|
737
738
|
name = "jsonschema-macros-core"
|
|
738
|
-
version = "0.48.
|
|
739
|
+
version = "0.48.5"
|
|
739
740
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
740
|
-
checksum = "
|
|
741
|
+
checksum = "5f884bf73113c53f6b1d23f14c68a09faebf118854ce122a1afe91ce73d050d3"
|
|
741
742
|
dependencies = [
|
|
742
743
|
"fancy-regex",
|
|
743
744
|
"indexmap",
|
|
@@ -754,7 +755,7 @@ dependencies = [
|
|
|
754
755
|
|
|
755
756
|
[[package]]
|
|
756
757
|
name = "jsonschema-rb-ext"
|
|
757
|
-
version = "0.48.
|
|
758
|
+
version = "0.48.5"
|
|
758
759
|
dependencies = [
|
|
759
760
|
"jsonschema",
|
|
760
761
|
"magnus",
|
|
@@ -767,13 +768,28 @@ dependencies = [
|
|
|
767
768
|
|
|
768
769
|
[[package]]
|
|
769
770
|
name = "jsonschema-regex"
|
|
770
|
-
version = "0.48.
|
|
771
|
+
version = "0.48.5"
|
|
771
772
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
772
|
-
checksum = "
|
|
773
|
+
checksum = "84708dd3f6c5327478a96f37378adb27deed6a626cf84d19de780d9e8ae84b17"
|
|
773
774
|
dependencies = [
|
|
774
775
|
"regex-syntax",
|
|
775
776
|
]
|
|
776
777
|
|
|
778
|
+
[[package]]
|
|
779
|
+
name = "jsonschema-value"
|
|
780
|
+
version = "0.48.5"
|
|
781
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
782
|
+
checksum = "fd8c04ab4ce60e42c4e302d3bd9d184652bb56f212495d2eea23573bcbf72556"
|
|
783
|
+
dependencies = [
|
|
784
|
+
"ahash",
|
|
785
|
+
"bytecount",
|
|
786
|
+
"fraction",
|
|
787
|
+
"num-bigint",
|
|
788
|
+
"num-cmp",
|
|
789
|
+
"num-traits",
|
|
790
|
+
"serde_json",
|
|
791
|
+
]
|
|
792
|
+
|
|
777
793
|
[[package]]
|
|
778
794
|
name = "lazy_static"
|
|
779
795
|
version = "1.5.0"
|
|
@@ -1114,9 +1130,9 @@ dependencies = [
|
|
|
1114
1130
|
|
|
1115
1131
|
[[package]]
|
|
1116
1132
|
name = "referencing"
|
|
1117
|
-
version = "0.48.
|
|
1133
|
+
version = "0.48.5"
|
|
1118
1134
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1119
|
-
checksum = "
|
|
1135
|
+
checksum = "980e77f5cfffc592c0e7dfb6d20770a0b96a6ab94d403de7454ed9799505e4ba"
|
|
1120
1136
|
dependencies = [
|
|
1121
1137
|
"ahash",
|
|
1122
1138
|
"fluent-uri",
|
data/ext/jsonschema/Cargo.toml
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "jsonschema-rb-ext"
|
|
3
|
-
version = "0.48.
|
|
3
|
+
version = "0.48.5"
|
|
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.48.
|
|
13
|
+
jsonschema = { version = "0.48.5", default-features = false, features = ["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.48.
|
|
16
|
+
referencing = "0.48.5"
|
|
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
|
@@ -14,8 +14,110 @@ module JSONSchema
|
|
|
14
14
|
# Main use case: deduplicate equivalent JSON Schemas by using a stable string form.
|
|
15
15
|
def self.to_string: (untyped object) -> String
|
|
16
16
|
end
|
|
17
|
+
|
|
18
|
+
# Structural discriminant of a canonical schema, one per view class.
|
|
19
|
+
type kind = :multi_type | :typed_group | :string | :integer | :const | :enum
|
|
20
|
+
| :any_of | :true | :false | :raw
|
|
21
|
+
|
|
22
|
+
type view = TrueView | FalseView | MultiTypeView | TypedGroupView | StringView
|
|
23
|
+
| IntegerView | AnyOfView | ConstView | EnumView | RawView
|
|
24
|
+
|
|
25
|
+
class CanonicalizationError < StandardError
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
class InvalidSchemaType < CanonicalizationError
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# A schema reduced to canonical form: schemas accepting the same values share one form.
|
|
32
|
+
class CanonicalSchema
|
|
33
|
+
def to_json_schema: () -> untyped
|
|
34
|
+
def draft: () -> JSONSchema::draft
|
|
35
|
+
def kind: () -> kind
|
|
36
|
+
def view: () -> view
|
|
37
|
+
def definitions: () -> Hash[String, CanonicalSchema]
|
|
38
|
+
def satisfiable?: () -> bool
|
|
39
|
+
def inspect: () -> String
|
|
40
|
+
def ==: (untyped other) -> bool
|
|
41
|
+
def eql?: (untyped other) -> bool
|
|
42
|
+
def hash: () -> Integer
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Matches any value.
|
|
46
|
+
class TrueView
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Matches no value.
|
|
50
|
+
class FalseView
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# A value matches iff its JSON type is in the set.
|
|
54
|
+
class MultiTypeView
|
|
55
|
+
def types: () -> Array[Symbol]
|
|
56
|
+
def inspect: () -> String
|
|
57
|
+
def deconstruct_keys: (untyped keys) -> Hash[Symbol, untyped]
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# A value matches iff its JSON type is `type_name` and it satisfies `body`.
|
|
61
|
+
class TypedGroupView
|
|
62
|
+
def type_name: () -> Symbol
|
|
63
|
+
def body: () -> CanonicalSchema
|
|
64
|
+
def inspect: () -> String
|
|
65
|
+
def deconstruct_keys: (untyped keys) -> Hash[Symbol, untyped]
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# A string value within a length window, matching every pattern.
|
|
69
|
+
class StringView
|
|
70
|
+
def min_length: () -> Integer?
|
|
71
|
+
def max_length: () -> Integer?
|
|
72
|
+
def patterns: () -> Array[String]
|
|
73
|
+
def inspect: () -> String
|
|
74
|
+
def deconstruct_keys: (untyped keys) -> Hash[Symbol, untyped]
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# An integer value within a closed interval.
|
|
78
|
+
class IntegerView
|
|
79
|
+
def minimum: () -> Integer?
|
|
80
|
+
def maximum: () -> Integer?
|
|
81
|
+
def inspect: () -> String
|
|
82
|
+
def deconstruct_keys: (untyped keys) -> Hash[Symbol, untyped]
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# A value matches iff at least one branch matches.
|
|
86
|
+
class AnyOfView
|
|
87
|
+
def branches: () -> Array[CanonicalSchema]
|
|
88
|
+
def inspect: () -> String
|
|
89
|
+
def deconstruct_keys: (untyped keys) -> Hash[Symbol, untyped]
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Exactly one admitted value.
|
|
93
|
+
class ConstView
|
|
94
|
+
def value: () -> untyped
|
|
95
|
+
def inspect: () -> String
|
|
96
|
+
def deconstruct_keys: (untyped keys) -> Hash[Symbol, untyped]
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# A sorted, deduplicated finite set of admitted values.
|
|
100
|
+
class EnumView
|
|
101
|
+
def values: () -> Array[untyped]
|
|
102
|
+
def inspect: () -> String
|
|
103
|
+
def deconstruct_keys: (untyped keys) -> Hash[Symbol, untyped]
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# A schema the canonical form does not model structurally, kept verbatim.
|
|
107
|
+
class RawView
|
|
108
|
+
def schema: () -> untyped
|
|
109
|
+
def inspect: () -> String
|
|
110
|
+
def deconstruct_keys: (untyped keys) -> Hash[Symbol, untyped]
|
|
111
|
+
end
|
|
17
112
|
end
|
|
18
113
|
|
|
114
|
+
# Reduce a schema to its canonical form.
|
|
115
|
+
def self.canonicalize: (
|
|
116
|
+
untyped schema,
|
|
117
|
+
?draft: draft?,
|
|
118
|
+
?validate_formats: bool?
|
|
119
|
+
) -> Canonical::CanonicalSchema
|
|
120
|
+
|
|
19
121
|
# Create a validator with auto-detected draft version.
|
|
20
122
|
#
|
|
21
123
|
# @param schema The JSON Schema (Hash or JSON string)
|
data/src/canonical.rs
CHANGED
|
@@ -91,13 +91,13 @@ impl RbCanonicalSchema {
|
|
|
91
91
|
rb_self.inner.is_satisfiable()
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
-
fn inspect(rb_self: &Self) -> String {
|
|
94
|
+
fn inspect(ruby: &Ruby, rb_self: &Self) -> String {
|
|
95
95
|
// Bounded: `inspect` runs implicitly (IRB, error messages) and a full
|
|
96
96
|
// `to_json_schema` re-emits the whole document.
|
|
97
97
|
format!(
|
|
98
|
-
"#<JSONSchema::Canonical::CanonicalSchema kind={} draft={
|
|
99
|
-
|
|
100
|
-
rb_self.
|
|
98
|
+
"#<JSONSchema::Canonical::CanonicalSchema kind={} draft={}>",
|
|
99
|
+
Self::kind(ruby, rb_self).inspect(),
|
|
100
|
+
Self::draft(ruby, rb_self).inspect()
|
|
101
101
|
)
|
|
102
102
|
}
|
|
103
103
|
|
|
@@ -125,6 +125,20 @@ impl RbCanonicalSchema {
|
|
|
125
125
|
CanonicalView::Enum(values) => ruby.obj_wrap(EnumView { values }).as_value(),
|
|
126
126
|
CanonicalView::True => ruby.obj_wrap(TrueView).as_value(),
|
|
127
127
|
CanonicalView::False => ruby.obj_wrap(FalseView).as_value(),
|
|
128
|
+
CanonicalView::String(view) => ruby
|
|
129
|
+
.obj_wrap(StringView {
|
|
130
|
+
min_length: view.min_length,
|
|
131
|
+
max_length: view.max_length,
|
|
132
|
+
patterns: view.patterns,
|
|
133
|
+
})
|
|
134
|
+
.as_value(),
|
|
135
|
+
CanonicalView::Integer(view) => ruby
|
|
136
|
+
.obj_wrap(IntegerView {
|
|
137
|
+
minimum: view.minimum,
|
|
138
|
+
maximum: view.maximum,
|
|
139
|
+
})
|
|
140
|
+
.as_value(),
|
|
141
|
+
CanonicalView::AnyOf(branches) => ruby.obj_wrap(AnyOfView { branches }).as_value(),
|
|
128
142
|
CanonicalView::Raw(schema) => ruby.obj_wrap(RawView { schema }).as_value(),
|
|
129
143
|
// TODO(canonical): new `CanonicalView` variants need view classes here.
|
|
130
144
|
other => unreachable!("unsupported canonical view: {other:?}"),
|
|
@@ -155,11 +169,11 @@ impl RawView {
|
|
|
155
169
|
value_to_ruby(ruby, &rb_self.schema)
|
|
156
170
|
}
|
|
157
171
|
|
|
158
|
-
fn inspect(rb_self: &Self) -> String {
|
|
159
|
-
format!(
|
|
172
|
+
fn inspect(ruby: &Ruby, rb_self: &Self) -> Result<String, Error> {
|
|
173
|
+
Ok(format!(
|
|
160
174
|
"#<JSONSchema::Canonical::RawView schema={}>",
|
|
161
|
-
rb_self
|
|
162
|
-
)
|
|
175
|
+
Self::schema(ruby, rb_self)?.inspect()
|
|
176
|
+
))
|
|
163
177
|
}
|
|
164
178
|
|
|
165
179
|
fn deconstruct_keys(ruby: &Ruby, rb_self: &Self, _keys: Value) -> Result<RHash, Error> {
|
|
@@ -177,6 +191,12 @@ impl RawView {
|
|
|
177
191
|
#[magnus(class = "JSONSchema::Canonical::TrueView", free_immediately)]
|
|
178
192
|
pub struct TrueView;
|
|
179
193
|
|
|
194
|
+
impl TrueView {
|
|
195
|
+
fn inspect(_rb_self: &Self) -> String {
|
|
196
|
+
"#<JSONSchema::Canonical::TrueView>".to_string()
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
180
200
|
impl DataTypeFunctions for TrueView {}
|
|
181
201
|
|
|
182
202
|
/// Matches no value.
|
|
@@ -184,6 +204,12 @@ impl DataTypeFunctions for TrueView {}
|
|
|
184
204
|
#[magnus(class = "JSONSchema::Canonical::FalseView", free_immediately)]
|
|
185
205
|
pub struct FalseView;
|
|
186
206
|
|
|
207
|
+
impl FalseView {
|
|
208
|
+
fn inspect(_rb_self: &Self) -> String {
|
|
209
|
+
"#<JSONSchema::Canonical::FalseView>".to_string()
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
187
213
|
impl DataTypeFunctions for FalseView {}
|
|
188
214
|
|
|
189
215
|
/// A value matches iff its JSON type is in `types`.
|
|
@@ -204,11 +230,11 @@ impl MultiTypeView {
|
|
|
204
230
|
Ok(array.as_value())
|
|
205
231
|
}
|
|
206
232
|
|
|
207
|
-
fn inspect(rb_self: &Self) -> String {
|
|
208
|
-
format!(
|
|
209
|
-
"#<JSONSchema::Canonical::MultiTypeView types={
|
|
210
|
-
rb_self
|
|
211
|
-
)
|
|
233
|
+
fn inspect(ruby: &Ruby, rb_self: &Self) -> Result<String, Error> {
|
|
234
|
+
Ok(format!(
|
|
235
|
+
"#<JSONSchema::Canonical::MultiTypeView types={}>",
|
|
236
|
+
Self::types(ruby, rb_self)?.inspect()
|
|
237
|
+
))
|
|
212
238
|
}
|
|
213
239
|
|
|
214
240
|
fn deconstruct_keys(ruby: &Ruby, rb_self: &Self, _keys: Value) -> Result<RHash, Error> {
|
|
@@ -240,10 +266,10 @@ impl TypedGroupView {
|
|
|
240
266
|
.as_value()
|
|
241
267
|
}
|
|
242
268
|
|
|
243
|
-
fn inspect(rb_self: &Self) -> String {
|
|
269
|
+
fn inspect(ruby: &Ruby, rb_self: &Self) -> String {
|
|
244
270
|
format!(
|
|
245
|
-
"#<JSONSchema::Canonical::TypedGroupView type_name={
|
|
246
|
-
rb_self.
|
|
271
|
+
"#<JSONSchema::Canonical::TypedGroupView type_name={}>",
|
|
272
|
+
Self::type_name(ruby, rb_self).inspect()
|
|
247
273
|
)
|
|
248
274
|
}
|
|
249
275
|
|
|
@@ -255,6 +281,136 @@ impl TypedGroupView {
|
|
|
255
281
|
}
|
|
256
282
|
}
|
|
257
283
|
|
|
284
|
+
/// An absent bound is `nil`; a present one keeps its exact value.
|
|
285
|
+
fn bound_to_ruby(ruby: &Ruby, bound: Option<&serde_json::Number>) -> Result<Value, Error> {
|
|
286
|
+
match bound {
|
|
287
|
+
Some(number) => value_to_ruby(ruby, &serde_json::Value::Number(number.clone())),
|
|
288
|
+
None => Ok(ruby.qnil().as_value()),
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/// A string value within a length window, matching every pattern.
|
|
293
|
+
#[derive(magnus::TypedData)]
|
|
294
|
+
#[magnus(class = "JSONSchema::Canonical::StringView", free_immediately)]
|
|
295
|
+
pub struct StringView {
|
|
296
|
+
min_length: Option<serde_json::Number>,
|
|
297
|
+
max_length: Option<serde_json::Number>,
|
|
298
|
+
patterns: Vec<String>,
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
impl DataTypeFunctions for StringView {}
|
|
302
|
+
|
|
303
|
+
impl StringView {
|
|
304
|
+
fn min_length(ruby: &Ruby, rb_self: &Self) -> Result<Value, Error> {
|
|
305
|
+
bound_to_ruby(ruby, rb_self.min_length.as_ref())
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
fn max_length(ruby: &Ruby, rb_self: &Self) -> Result<Value, Error> {
|
|
309
|
+
bound_to_ruby(ruby, rb_self.max_length.as_ref())
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
fn patterns(ruby: &Ruby, rb_self: &Self) -> Result<Value, Error> {
|
|
313
|
+
let array = ruby.ary_new_capa(rb_self.patterns.len());
|
|
314
|
+
for pattern in &rb_self.patterns {
|
|
315
|
+
array.push(ruby.str_new(pattern).as_value())?;
|
|
316
|
+
}
|
|
317
|
+
Ok(array.as_value())
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
fn inspect(ruby: &Ruby, rb_self: &Self) -> Result<String, Error> {
|
|
321
|
+
Ok(format!(
|
|
322
|
+
"#<JSONSchema::Canonical::StringView min_length={} max_length={} patterns={}>",
|
|
323
|
+
Self::min_length(ruby, rb_self)?.inspect(),
|
|
324
|
+
Self::max_length(ruby, rb_self)?.inspect(),
|
|
325
|
+
Self::patterns(ruby, rb_self)?.inspect()
|
|
326
|
+
))
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
fn deconstruct_keys(ruby: &Ruby, rb_self: &Self, _keys: Value) -> Result<RHash, Error> {
|
|
330
|
+
let hash = ruby.hash_new();
|
|
331
|
+
hash.aset(ruby.sym_new("min_length"), Self::min_length(ruby, rb_self)?)?;
|
|
332
|
+
hash.aset(ruby.sym_new("max_length"), Self::max_length(ruby, rb_self)?)?;
|
|
333
|
+
hash.aset(ruby.sym_new("patterns"), Self::patterns(ruby, rb_self)?)?;
|
|
334
|
+
Ok(hash)
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/// An integer value within a closed interval.
|
|
339
|
+
#[derive(magnus::TypedData)]
|
|
340
|
+
#[magnus(class = "JSONSchema::Canonical::IntegerView", free_immediately)]
|
|
341
|
+
pub struct IntegerView {
|
|
342
|
+
minimum: Option<serde_json::Number>,
|
|
343
|
+
maximum: Option<serde_json::Number>,
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
impl DataTypeFunctions for IntegerView {}
|
|
347
|
+
|
|
348
|
+
impl IntegerView {
|
|
349
|
+
fn minimum(ruby: &Ruby, rb_self: &Self) -> Result<Value, Error> {
|
|
350
|
+
bound_to_ruby(ruby, rb_self.minimum.as_ref())
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
fn maximum(ruby: &Ruby, rb_self: &Self) -> Result<Value, Error> {
|
|
354
|
+
bound_to_ruby(ruby, rb_self.maximum.as_ref())
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
fn inspect(ruby: &Ruby, rb_self: &Self) -> Result<String, Error> {
|
|
358
|
+
Ok(format!(
|
|
359
|
+
"#<JSONSchema::Canonical::IntegerView minimum={} maximum={}>",
|
|
360
|
+
Self::minimum(ruby, rb_self)?.inspect(),
|
|
361
|
+
Self::maximum(ruby, rb_self)?.inspect()
|
|
362
|
+
))
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
fn deconstruct_keys(ruby: &Ruby, rb_self: &Self, _keys: Value) -> Result<RHash, Error> {
|
|
366
|
+
let hash = ruby.hash_new();
|
|
367
|
+
hash.aset(ruby.sym_new("minimum"), Self::minimum(ruby, rb_self)?)?;
|
|
368
|
+
hash.aset(ruby.sym_new("maximum"), Self::maximum(ruby, rb_self)?)?;
|
|
369
|
+
Ok(hash)
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
/// A value matches iff at least one branch matches.
|
|
374
|
+
#[derive(magnus::TypedData)]
|
|
375
|
+
#[magnus(class = "JSONSchema::Canonical::AnyOfView", free_immediately)]
|
|
376
|
+
pub struct AnyOfView {
|
|
377
|
+
branches: Vec<CanonicalSchema>,
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
impl DataTypeFunctions for AnyOfView {}
|
|
381
|
+
|
|
382
|
+
impl AnyOfView {
|
|
383
|
+
fn branches(ruby: &Ruby, rb_self: &Self) -> Result<Value, Error> {
|
|
384
|
+
let array = ruby.ary_new_capa(rb_self.branches.len());
|
|
385
|
+
for branch in &rb_self.branches {
|
|
386
|
+
array.push(
|
|
387
|
+
ruby.obj_wrap(RbCanonicalSchema {
|
|
388
|
+
inner: branch.clone(),
|
|
389
|
+
})
|
|
390
|
+
.as_value(),
|
|
391
|
+
)?;
|
|
392
|
+
}
|
|
393
|
+
Ok(array.as_value())
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
fn inspect(ruby: &Ruby, rb_self: &Self) -> Result<String, Error> {
|
|
397
|
+
let kinds = ruby.ary_new_capa(rb_self.branches.len());
|
|
398
|
+
for branch in &rb_self.branches {
|
|
399
|
+
kinds.push(ruby.sym_new(branch.kind().as_str()).as_value())?;
|
|
400
|
+
}
|
|
401
|
+
Ok(format!(
|
|
402
|
+
"#<JSONSchema::Canonical::AnyOfView branches={}>",
|
|
403
|
+
kinds.as_value().inspect()
|
|
404
|
+
))
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
fn deconstruct_keys(ruby: &Ruby, rb_self: &Self, _keys: Value) -> Result<RHash, Error> {
|
|
408
|
+
let hash = ruby.hash_new();
|
|
409
|
+
hash.aset(ruby.sym_new("branches"), Self::branches(ruby, rb_self)?)?;
|
|
410
|
+
Ok(hash)
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
|
|
258
414
|
/// Exactly one admitted value.
|
|
259
415
|
#[derive(magnus::TypedData)]
|
|
260
416
|
#[magnus(class = "JSONSchema::Canonical::ConstView", free_immediately)]
|
|
@@ -269,11 +425,11 @@ impl ConstView {
|
|
|
269
425
|
value_to_ruby(ruby, &rb_self.value)
|
|
270
426
|
}
|
|
271
427
|
|
|
272
|
-
fn inspect(rb_self: &Self) -> String {
|
|
273
|
-
format!(
|
|
428
|
+
fn inspect(ruby: &Ruby, rb_self: &Self) -> Result<String, Error> {
|
|
429
|
+
Ok(format!(
|
|
274
430
|
"#<JSONSchema::Canonical::ConstView value={}>",
|
|
275
|
-
rb_self
|
|
276
|
-
)
|
|
431
|
+
Self::value(ruby, rb_self)?.inspect()
|
|
432
|
+
))
|
|
277
433
|
}
|
|
278
434
|
|
|
279
435
|
fn deconstruct_keys(ruby: &Ruby, rb_self: &Self, _keys: Value) -> Result<RHash, Error> {
|
|
@@ -301,11 +457,11 @@ impl EnumView {
|
|
|
301
457
|
Ok(array.as_value())
|
|
302
458
|
}
|
|
303
459
|
|
|
304
|
-
fn inspect(rb_self: &Self) -> String {
|
|
305
|
-
format!(
|
|
306
|
-
"#<JSONSchema::Canonical::EnumView values={
|
|
307
|
-
rb_self
|
|
308
|
-
)
|
|
460
|
+
fn inspect(ruby: &Ruby, rb_self: &Self) -> Result<String, Error> {
|
|
461
|
+
Ok(format!(
|
|
462
|
+
"#<JSONSchema::Canonical::EnumView values={}>",
|
|
463
|
+
Self::values(ruby, rb_self)?.inspect()
|
|
464
|
+
))
|
|
309
465
|
}
|
|
310
466
|
|
|
311
467
|
fn deconstruct_keys(ruby: &Ruby, rb_self: &Self, _keys: Value) -> Result<RHash, Error> {
|
|
@@ -368,8 +524,10 @@ pub(crate) fn init_canonical(ruby: &Ruby, module: &RModule) -> Result<(), Error>
|
|
|
368
524
|
canonical_schema.define_method("definitions", method!(RbCanonicalSchema::definitions, 0))?;
|
|
369
525
|
canonical_schema.define_method("satisfiable?", method!(RbCanonicalSchema::satisfiable, 0))?;
|
|
370
526
|
|
|
371
|
-
canonical_module.define_class("TrueView", ruby.class_object())?;
|
|
372
|
-
|
|
527
|
+
let true_view = canonical_module.define_class("TrueView", ruby.class_object())?;
|
|
528
|
+
true_view.define_method("inspect", method!(TrueView::inspect, 0))?;
|
|
529
|
+
let false_view = canonical_module.define_class("FalseView", ruby.class_object())?;
|
|
530
|
+
false_view.define_method("inspect", method!(FalseView::inspect, 0))?;
|
|
373
531
|
|
|
374
532
|
let multi_type_view = canonical_module.define_class("MultiTypeView", ruby.class_object())?;
|
|
375
533
|
multi_type_view.define_method("types", method!(MultiTypeView::types, 0))?;
|
|
@@ -398,6 +556,27 @@ pub(crate) fn init_canonical(ruby: &Ruby, module: &RModule) -> Result<(), Error>
|
|
|
398
556
|
enum_view.define_method("inspect", method!(EnumView::inspect, 0))?;
|
|
399
557
|
enum_view.define_method("deconstruct_keys", method!(EnumView::deconstruct_keys, 1))?;
|
|
400
558
|
|
|
559
|
+
let string_view = canonical_module.define_class("StringView", ruby.class_object())?;
|
|
560
|
+
string_view.define_method("min_length", method!(StringView::min_length, 0))?;
|
|
561
|
+
string_view.define_method("max_length", method!(StringView::max_length, 0))?;
|
|
562
|
+
string_view.define_method("patterns", method!(StringView::patterns, 0))?;
|
|
563
|
+
string_view.define_method("inspect", method!(StringView::inspect, 0))?;
|
|
564
|
+
string_view.define_method("deconstruct_keys", method!(StringView::deconstruct_keys, 1))?;
|
|
565
|
+
|
|
566
|
+
let integer_view = canonical_module.define_class("IntegerView", ruby.class_object())?;
|
|
567
|
+
integer_view.define_method("minimum", method!(IntegerView::minimum, 0))?;
|
|
568
|
+
integer_view.define_method("maximum", method!(IntegerView::maximum, 0))?;
|
|
569
|
+
integer_view.define_method("inspect", method!(IntegerView::inspect, 0))?;
|
|
570
|
+
integer_view.define_method(
|
|
571
|
+
"deconstruct_keys",
|
|
572
|
+
method!(IntegerView::deconstruct_keys, 1),
|
|
573
|
+
)?;
|
|
574
|
+
|
|
575
|
+
let any_of_view = canonical_module.define_class("AnyOfView", ruby.class_object())?;
|
|
576
|
+
any_of_view.define_method("branches", method!(AnyOfView::branches, 0))?;
|
|
577
|
+
any_of_view.define_method("inspect", method!(AnyOfView::inspect, 0))?;
|
|
578
|
+
any_of_view.define_method("deconstruct_keys", method!(AnyOfView::deconstruct_keys, 1))?;
|
|
579
|
+
|
|
401
580
|
let raw_view = canonical_module.define_class("RawView", ruby.class_object())?;
|
|
402
581
|
raw_view.define_method("schema", method!(RawView::schema, 0))?;
|
|
403
582
|
raw_view.define_method("inspect", method!(RawView::inspect, 0))?;
|