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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7091a24d3c4cae1381d2dcc89844c0c9e2752a04e418a94ded9b3e93656fe9f8
4
- data.tar.gz: c2367c71d93a857f2520dd345e26222608714868e2941a332eb30d78816f75a4
3
+ metadata.gz: 60ae1d2ffaa7543f17f5a7953a2ed92520f3887f7e92c8c8ac632f7c56e515ef
4
+ data.tar.gz: 8c3ac5d3f66016a881eed8a6f9f78327e32373e738ab453c39f0449365fce8a9
5
5
  SHA512:
6
- metadata.gz: a7dea5681e119df671ac136f7fb9a780e3ac12354487ed763aef6cb7c0f9c68357287a66a17745a2778d78d9aaa5d33faa41de4bbb19f9d7f7b17bbb2285da4a
7
- data.tar.gz: 9c8544d8e5379e5d7013fbed284ef7e932894f23900973a5901a6cb6a40022fbb170bd30ecee04555cf2d512fe3a7a5778e9bff5e809556e9c0a2845a21f70da
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.2...HEAD
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.2"
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.2", default-features = false, features = ["arbitrary-precision", "resolve-http", "resolve-file", "tls-ring", "macros"] }
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 }
@@ -693,9 +693,9 @@ dependencies = [
693
693
 
694
694
  [[package]]
695
695
  name = "jsonschema"
696
- version = "0.48.2"
696
+ version = "0.48.5"
697
697
  source = "registry+https://github.com/rust-lang/crates.io-index"
698
- checksum = "39d785c0683d1027839f1ac6a43b6d07c63d58ecd363d8146dda4531d53465a1"
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.2"
729
+ version = "0.48.5"
729
730
  source = "registry+https://github.com/rust-lang/crates.io-index"
730
- checksum = "a1c58940755c1f87fc5843b63626867ed8384bc0b6fabf0de2a718ccafb42570"
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.2"
739
+ version = "0.48.5"
739
740
  source = "registry+https://github.com/rust-lang/crates.io-index"
740
- checksum = "110e53690c5d5524b69e557bd286b1c6c9743bfcf13c18fd5e3f21a9708737dc"
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.2"
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.2"
771
+ version = "0.48.5"
771
772
  source = "registry+https://github.com/rust-lang/crates.io-index"
772
- checksum = "917b3be16b2662538aafb55201790561e1f1ad1a0454baf42f33bd9de343778b"
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.2"
1133
+ version = "0.48.5"
1118
1134
  source = "registry+https://github.com/rust-lang/crates.io-index"
1119
- checksum = "2d2b21a85c07fcf1cb95ff7ab8a687fcd37fa70db59975b5a032abdaadfdf42e"
1135
+ checksum = "980e77f5cfffc592c0e7dfb6d20770a0b96a6ab94d403de7454ed9799505e4ba"
1120
1136
  dependencies = [
1121
1137
  "ahash",
1122
1138
  "fluent-uri",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "jsonschema-rb-ext"
3
- version = "0.48.2"
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.2", default-features = false, features = ["arbitrary-precision", "resolve-http", "resolve-file", "tls-ring", "macros"] }
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.2"
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"
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module JSONSchema
4
- VERSION = "0.48.2"
4
+ VERSION = "0.48.5"
5
5
  end
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
- rb_self.inner.kind().as_str(),
100
- rb_self.inner.draft()
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.schema
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.types
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.type_name
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.value
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.values
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
- canonical_module.define_class("FalseView", ruby.class_object())?;
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))?;
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jsonschema_rs
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.48.2
4
+ version: 0.48.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dmitry Dygalo