jsonschema_rs 0.49.5 → 0.49.7

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: 14182b3d65f8580de3c3c3b3dab17d0709a70e56b93b519a2095f0d87bbda232
4
- data.tar.gz: c43c5b754ef7a41ff8ce3d06ab79f1f29854967446ee6efb76282af7c0186e98
3
+ metadata.gz: 2b3388bbb4302ddf7e4c108df32d945f68074c7baac52e85aa19964bbd8d8cec
4
+ data.tar.gz: 9a833159377a6b7673007129536b9d3997f01b1d1cd4226a51efa358c5ef6daa
5
5
  SHA512:
6
- metadata.gz: 503c06fb04a59e9ca5e38eeb0c360741a9d6a409e4dce784ade9babe4514f19fb1f4668b9f21538e661c5bed1d76600cd32ec92bd4c7d1daa8a6e147de4b3607
7
- data.tar.gz: 53b2d54cbbb81a4b2ccba5eaa7a8cf8144f1597c3ccbf0abf55ba0fbee189a85634a936a5571af77d64e4a9351c04ec57f41867decb15b1404beeb93bc7a0abc
6
+ metadata.gz: dec67420394656cbbaf899553338fa8525680018f548ba94470713bb66a057f6361cc4d93b98763b3c739233eab7df7bfb954eae2d9745fffd41a300df361b9a
7
+ data.tar.gz: 418f555ee5c68ed4a4932e6c9230ee0a8e3e5e8b5c92739d9007c959b305d99f68e272fc5cda0b2114751e50146528d478bf9c3cfaefb44399ddb97677fa8c23
data/CHANGELOG.md CHANGED
@@ -2,6 +2,64 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [0.49.7] - 2026-08-08
6
+
7
+ ### Added
8
+
9
+ - `retriever`, `registry`, and `base_uri` keyword arguments to `JSONSchema.canonicalize`.
10
+ - Canonicalization of a `oneOf` whose branches name disjoint targets, which degrades to a union.
11
+ - Canonicalization of a vacuous `patternProperties` entry beside schema-valued `additionalProperties`, where matching keys escape its value constraint.
12
+ - Canonicalization of a Draft 4 closed pattern map with a reference nested under a property.
13
+ - Canonicalization of Draft 4 closed pattern maps that meet through an applicator.
14
+ - The complement of a reference back to a target already being negated, which stays symbolic instead of declining.
15
+ - `CanonicalSchema#definition` resolving `#` to the document the schema was read against.
16
+
17
+ ### Performance
18
+
19
+ - Up to 150x faster canonicalization of `not` over a union of many branches.
20
+ - 2% faster emission of canonical schemas, which no longer formats copied string values.
21
+ - 5% faster emission of canonical schemas, which no longer formats object keys while copying them.
22
+ - Up to 12% faster canonicalization of schemas that repeatedly intersect the same branches.
23
+ - 13% faster canonicalization of a non-dynamic OpenAPI document, which no longer scans every schema object for dynamic references.
24
+ - Faster canonicalization of schemas with local `$defs` references, which avoid decoding unescaped definition names.
25
+ - 23% faster canonicalization of an object whose keys a finite property-name set spells.
26
+ - 3% faster intersection of schemas where one side constrains nothing.
27
+ - Up to 31x faster canonicalization of a `oneOf` whose many branches overlap.
28
+ - Up to 14x faster canonicalization of a union whose object branches share no values.
29
+ - 7% faster canonicalization of schemas that reach the same pair of nodes repeatedly.
30
+ - 5% faster canonicalization of objects, whose property maps no longer reach the allocator.
31
+ - Up to 8% faster canonicalization of schemas that reach `true` and `false` subschemas repeatedly.
32
+ - 2% faster canonicalization of schemas that assert known string formats.
33
+
34
+ ### Fixed
35
+
36
+ - `CanonicalSchema#definition` and `CanonicalSchema#definitions` handing out a target that names the document root without that document, where `#` points at the target instead.
37
+ - An `items` tail beyond an array's length ceiling surviving canonicalization, where it governs no element.
38
+ - `CanonicalSchema#to_json_schema` leaving the document root out of a node emitted below it, where `#` points at that node instead.
39
+
40
+ ## [0.49.6] - 2026-08-06
41
+
42
+ ### Added
43
+
44
+ - Canonicalization of a negated `uniqueItems`, where the complement demands a repeated element under the length floor two elements imply.
45
+ - Canonicalization of a negated array tuple, where each position's complement stands under the length that reaches it.
46
+ - Canonicalization of `contains` demands sharing no value, where their counts add up into a length floor.
47
+ - `CanonicalSchema#negate` through references, where the complement of the resolved target takes the reference's place.
48
+ - Canonicalization of negated `propertyNames` and `additionalProperties`, where the complement spells the violating-key demand instead of a `not` residual.
49
+ - Canonicalization of negated `additionalProperties` under Draft 4, where the violating-key demand spells the closed property map.
50
+ - Canonicalization of `not` a reference, where the complement of the resolved target takes the pointer's place.
51
+ - Canonicalization of a negated `oneOf`, where the complement spells the values no branch admits beside the values two branches share.
52
+ - Canonicalization of negated `items` under Draft 4, where the violating-element demand spells the barred element schema.
53
+
54
+ ### Changed
55
+
56
+ - `ArrayView` reports distinctness in three states, so an array demanding a repeated element reads apart from one demanding distinct elements.
57
+
58
+ ### Fixed
59
+
60
+ - `CanonicalSchema#negate` keeping a root self-reference in the complement, where it points at the complement instead of the source.
61
+ - An `additionalItems` that tails no tuple keeping the whole document unmodeled under Draft 2020-12.
62
+
5
63
  ## [0.49.5] - 2026-08-05
6
64
 
7
65
  ### Added
@@ -304,7 +362,9 @@
304
362
 
305
363
  - Initial public release
306
364
 
307
- [Unreleased]: https://github.com/Stranger6667/jsonschema/compare/ruby-v0.49.5...HEAD
365
+ [Unreleased]: https://github.com/Stranger6667/jsonschema/compare/ruby-v0.49.7...HEAD
366
+ [0.49.7]: https://github.com/Stranger6667/jsonschema/compare/ruby-v0.49.6...ruby-v0.49.7
367
+ [0.49.6]: https://github.com/Stranger6667/jsonschema/compare/ruby-v0.49.5...ruby-v0.49.6
308
368
  [0.49.5]: https://github.com/Stranger6667/jsonschema/compare/ruby-v0.49.4...ruby-v0.49.5
309
369
  [0.49.4]: https://github.com/Stranger6667/jsonschema/compare/ruby-v0.49.3...ruby-v0.49.4
310
370
  [0.49.3]: https://github.com/Stranger6667/jsonschema/compare/ruby-v0.49.2...ruby-v0.49.3
data/Cargo.toml CHANGED
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "jsonschema-rb"
3
- version = "0.49.5"
3
+ version = "0.49.7"
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.5", default-features = false, features = ["magnus", "arbitrary-precision", "resolve-http", "resolve-file", "tls-ring", "macros"] }
16
+ jsonschema = { version = "0.49.7", 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 }
@@ -693,9 +693,9 @@ dependencies = [
693
693
 
694
694
  [[package]]
695
695
  name = "jsonschema"
696
- version = "0.49.5"
696
+ version = "0.49.7"
697
697
  source = "registry+https://github.com/rust-lang/crates.io-index"
698
- checksum = "8da60094fc1968bbd091e2cfa004415cb7b19e25e592376e66a64aa832bb6039"
698
+ checksum = "ca4b985be36e5b3d15162b16ca94ac18c2a0514f5598b23b9d769895cb56bc3c"
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.5"
729
+ version = "0.49.7"
730
730
  source = "registry+https://github.com/rust-lang/crates.io-index"
731
- checksum = "1575f559a96e0cd2b83afd25b868507d39b97e16af2ed7d23074c470b0259627"
731
+ checksum = "de1ff79046715d10fe5fd795c0f562d8f2e41f470bed5fcad74a0c9f5fd5a6b8"
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.5"
739
+ version = "0.49.7"
740
740
  source = "registry+https://github.com/rust-lang/crates.io-index"
741
- checksum = "4d2d8f4ec940ac30dc8e85787916ac6a9d34fcfa850b47ffe69205e837dee621"
741
+ checksum = "8888005b18cbb6b61b4cb5fb4ae5f20b45dde81ab59baf37897b4668ba58a6f3"
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.5"
758
+ version = "0.49.7"
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.5"
771
+ version = "0.49.7"
772
772
  source = "registry+https://github.com/rust-lang/crates.io-index"
773
- checksum = "36539f34ef9e5da418433fbbf7294522d8f930ecf6a540ccd1ec6481c9ff9056"
773
+ checksum = "614c05e01260d4532d9ad28d66185fa1d93d015c5d610cde70d4b7143d7fb98f"
774
774
  dependencies = [
775
775
  "regex-syntax",
776
776
  ]
777
777
 
778
778
  [[package]]
779
779
  name = "jsonschema-value"
780
- version = "0.49.5"
780
+ version = "0.49.7"
781
781
  source = "registry+https://github.com/rust-lang/crates.io-index"
782
- checksum = "8bc513dfee68c6fe29498451df95a32951ea227801b476f4a1f236433986c891"
782
+ checksum = "8602a6850f24cf05c518f58c9b8d08e32a28b9848115c8e193693db0952353f6"
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.5"
1135
+ version = "0.49.7"
1136
1136
  source = "registry+https://github.com/rust-lang/crates.io-index"
1137
- checksum = "05915176d843da9ec5c925e5e2631be9aa61b27430acfdd562e79cae8f559725"
1137
+ checksum = "0753550862a089302b186486dfb843f2d547415257d78c32ae0d169e4d6784d1"
1138
1138
  dependencies = [
1139
1139
  "ahash",
1140
1140
  "fluent-uri",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "jsonschema-rb-ext"
3
- version = "0.49.5"
3
+ version = "0.49.7"
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.5", default-features = false, features = ["magnus", "arbitrary-precision", "resolve-http", "resolve-file", "tls-ring", "macros"] }
13
+ jsonschema = { version = "0.49.7", 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.5"
16
+ referencing = "0.49.7"
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.49.5"
4
+ VERSION = "0.49.7"
5
5
  end
data/sig/jsonschema.rbs CHANGED
@@ -121,7 +121,7 @@ module JSONSchema
121
121
  class ArrayView
122
122
  def min_items: () -> Integer?
123
123
  def max_items: () -> Integer?
124
- def unique_items: () -> bool
124
+ def distinctness: () -> (:unconstrained | :all_distinct | :some_repeated)
125
125
  def prefix_items: () -> Array[CanonicalSchema]
126
126
  def items: () -> CanonicalSchema?
127
127
  def contains: () -> Array[ContainsView]
@@ -146,6 +146,24 @@ module JSONSchema
146
146
  def property_names: () -> CanonicalSchema?
147
147
  def properties: () -> Hash[String, CanonicalSchema]
148
148
  def pattern_properties: () -> Hash[String, CanonicalSchema]
149
+ def additional_properties: () -> CanonicalSchema?
150
+ def violations: () -> Array[NameFailsView | UndeclaredValueFailsView]
151
+ def inspect: () -> String
152
+ def deconstruct_keys: (untyped keys) -> Hash[Symbol, untyped]
153
+ end
154
+
155
+ # Some key's name fails the schema.
156
+ class NameFailsView
157
+ def schema: () -> CanonicalSchema
158
+ def inspect: () -> String
159
+ def deconstruct_keys: (untyped keys) -> Hash[Symbol, untyped]
160
+ end
161
+
162
+ # Some key outside `names` and matching none of `patterns` has a value failing `additional`.
163
+ class UndeclaredValueFailsView
164
+ def names: () -> Array[String]
165
+ def patterns: () -> Array[String]
166
+ def additional: () -> CanonicalSchema
149
167
  def inspect: () -> String
150
168
  def deconstruct_keys: (untyped keys) -> Hash[Symbol, untyped]
151
169
  end
@@ -184,7 +202,10 @@ module JSONSchema
184
202
  untyped schema,
185
203
  ?draft: draft?,
186
204
  ?validate_formats: bool?,
187
- ?pattern_options: (RegexOptions | FancyRegexOptions)?
205
+ ?pattern_options: (RegexOptions | FancyRegexOptions)?,
206
+ ?retriever: (^(String) -> untyped)?,
207
+ ?registry: Registry?,
208
+ ?base_uri: String?
188
209
  ) -> Canonical::CanonicalSchema
189
210
 
190
211
  # Create a validator with auto-detected draft version.
data/src/canonical.rs CHANGED
@@ -1,6 +1,7 @@
1
1
  use jsonschema::{
2
2
  canonical::{
3
3
  CanonicalSchema, CanonicalView, CanonicalizationError, ContainsView as CoreContainsView,
4
+ ObjectViolationView as CoreObjectViolationView,
4
5
  },
5
6
  JsonType,
6
7
  };
@@ -14,7 +15,12 @@ use magnus::{
14
15
  };
15
16
 
16
17
  use crate::{
17
- options::{extract_pattern_options, parse_draft_symbol, RbPatternOptions},
18
+ options::{
19
+ extract_pattern_options, parse_draft_symbol, RbPatternOptions, KW_BASE_URI, KW_REGISTRY,
20
+ KW_RETRIEVER,
21
+ },
22
+ registry::Registry,
23
+ retriever::make_retriever,
18
24
  ser::{to_schema_value, value_to_ruby},
19
25
  static_id::define_rb_intern,
20
26
  };
@@ -23,8 +29,18 @@ define_rb_intern!(static CANONICAL_KW_DRAFT: "draft");
23
29
  define_rb_intern!(static CANONICAL_KW_VALIDATE_FORMATS: "validate_formats");
24
30
  define_rb_intern!(static CANONICAL_KW_PATTERN_OPTIONS: "pattern_options");
25
31
 
26
- type CanonicalKwArgs =
27
- magnus::scan_args::KwArgs<(), (Option<Value>, Option<bool>, Option<Value>), ()>;
32
+ type CanonicalKwArgs = magnus::scan_args::KwArgs<
33
+ (),
34
+ (
35
+ Option<Value>,
36
+ Option<bool>,
37
+ Option<Value>,
38
+ Option<Value>,
39
+ Option<Value>,
40
+ Option<String>,
41
+ ),
42
+ (),
43
+ >;
28
44
 
29
45
  macro_rules! canonical_error_class {
30
46
  ($static_name:ident, $class_name:literal) => {
@@ -179,7 +195,7 @@ impl RbCanonicalSchema {
179
195
  .obj_wrap(ArrayView {
180
196
  min_items: view.min_items,
181
197
  max_items: view.max_items,
182
- unique_items: view.unique_items,
198
+ distinctness: view.distinctness.as_str(),
183
199
  prefix_items: view.prefix_items,
184
200
  items: view.items,
185
201
  contains: view.contains,
@@ -194,6 +210,7 @@ impl RbCanonicalSchema {
194
210
  properties: view.properties,
195
211
  pattern_properties: view.pattern_properties,
196
212
  additional_properties: view.additional_properties,
213
+ violations: view.violations,
197
214
  })
198
215
  .as_value(),
199
216
  CanonicalView::Not(schema) => ruby.obj_wrap(NotView { schema: *schema }).as_value(),
@@ -641,7 +658,7 @@ impl IntegerView {
641
658
  pub struct ArrayView {
642
659
  min_items: Option<serde_json::Number>,
643
660
  max_items: Option<serde_json::Number>,
644
- unique_items: bool,
661
+ distinctness: &'static str,
645
662
  prefix_items: Vec<CanonicalSchema>,
646
663
  items: Option<CanonicalSchema>,
647
664
  contains: Vec<CoreContainsView>,
@@ -658,8 +675,8 @@ impl ArrayView {
658
675
  bound_to_ruby(ruby, rb_self.max_items.as_ref())
659
676
  }
660
677
 
661
- fn unique_items(ruby: &Ruby, rb_self: &Self) -> Value {
662
- ruby.into_value(rb_self.unique_items)
678
+ fn distinctness(ruby: &Ruby, rb_self: &Self) -> Value {
679
+ ruby.sym_new(rb_self.distinctness).as_value()
663
680
  }
664
681
 
665
682
  fn prefix_items(ruby: &Ruby, rb_self: &Self) -> Result<Value, Error> {
@@ -696,10 +713,10 @@ impl ArrayView {
696
713
 
697
714
  fn inspect(ruby: &Ruby, rb_self: &Self) -> Result<String, Error> {
698
715
  Ok(format!(
699
- "#<JSONSchema::Canonical::ArrayView min_items={} max_items={} unique_items={} prefix_items={} items={} contains={}>",
716
+ "#<JSONSchema::Canonical::ArrayView min_items={} max_items={} distinctness={} prefix_items={} items={} contains={}>",
700
717
  Self::min_items(ruby, rb_self)?.inspect(),
701
718
  Self::max_items(ruby, rb_self)?.inspect(),
702
- Self::unique_items(ruby, rb_self).inspect(),
719
+ Self::distinctness(ruby, rb_self).inspect(),
703
720
  Self::prefix_items(ruby, rb_self)?.inspect(),
704
721
  Self::items(ruby, rb_self).inspect(),
705
722
  Self::contains(ruby, rb_self)?.inspect()
@@ -711,8 +728,8 @@ impl ArrayView {
711
728
  hash.aset(ruby.sym_new("min_items"), Self::min_items(ruby, rb_self)?)?;
712
729
  hash.aset(ruby.sym_new("max_items"), Self::max_items(ruby, rb_self)?)?;
713
730
  hash.aset(
714
- ruby.sym_new("unique_items"),
715
- Self::unique_items(ruby, rb_self),
731
+ ruby.sym_new("distinctness"),
732
+ Self::distinctness(ruby, rb_self),
716
733
  )?;
717
734
  hash.aset(
718
735
  ruby.sym_new("prefix_items"),
@@ -783,6 +800,116 @@ impl ContainsView {
783
800
  }
784
801
  }
785
802
 
803
+ // The violation list needs the same lazy Ruby-object conversion `ContainsView::from_core` does,
804
+ // so this stays a free function rather than a method on either violation view class.
805
+ fn object_violation_to_ruby(ruby: &Ruby, violation: &CoreObjectViolationView) -> Value {
806
+ match violation {
807
+ CoreObjectViolationView::NameFails(schema) => ruby
808
+ .obj_wrap(NameFailsView {
809
+ schema: schema.clone(),
810
+ })
811
+ .as_value(),
812
+ CoreObjectViolationView::UndeclaredValueFails {
813
+ names,
814
+ patterns,
815
+ additional,
816
+ } => ruby
817
+ .obj_wrap(UndeclaredValueFailsView {
818
+ names: names.clone(),
819
+ patterns: patterns.clone(),
820
+ additional: additional.clone(),
821
+ })
822
+ .as_value(),
823
+ }
824
+ }
825
+
826
+ /// Some key's name fails the schema.
827
+ #[derive(magnus::TypedData)]
828
+ #[magnus(class = "JSONSchema::Canonical::NameFailsView", free_immediately)]
829
+ pub struct NameFailsView {
830
+ schema: CanonicalSchema,
831
+ }
832
+
833
+ impl DataTypeFunctions for NameFailsView {}
834
+
835
+ impl NameFailsView {
836
+ fn schema(ruby: &Ruby, rb_self: &Self) -> Value {
837
+ ruby.obj_wrap(RbCanonicalSchema {
838
+ inner: rb_self.schema.clone(),
839
+ })
840
+ .as_value()
841
+ }
842
+
843
+ fn inspect(ruby: &Ruby, rb_self: &Self) -> String {
844
+ format!(
845
+ "#<JSONSchema::Canonical::NameFailsView schema={}>",
846
+ Self::schema(ruby, rb_self).inspect()
847
+ )
848
+ }
849
+
850
+ fn deconstruct_keys(ruby: &Ruby, rb_self: &Self, _keys: Value) -> Result<RHash, Error> {
851
+ let hash = ruby.hash_new();
852
+ hash.aset(ruby.sym_new("schema"), Self::schema(ruby, rb_self))?;
853
+ Ok(hash)
854
+ }
855
+ }
856
+
857
+ /// Some key outside `names` and matching none of `patterns` has a value failing `additional`.
858
+ #[derive(magnus::TypedData)]
859
+ #[magnus(
860
+ class = "JSONSchema::Canonical::UndeclaredValueFailsView",
861
+ free_immediately
862
+ )]
863
+ pub struct UndeclaredValueFailsView {
864
+ names: Vec<String>,
865
+ patterns: Vec<String>,
866
+ additional: CanonicalSchema,
867
+ }
868
+
869
+ impl DataTypeFunctions for UndeclaredValueFailsView {}
870
+
871
+ impl UndeclaredValueFailsView {
872
+ fn names(ruby: &Ruby, rb_self: &Self) -> Result<Value, Error> {
873
+ let array = ruby.ary_new_capa(rb_self.names.len());
874
+ for name in &rb_self.names {
875
+ array.push(ruby.str_new(name))?;
876
+ }
877
+ Ok(array.as_value())
878
+ }
879
+
880
+ fn patterns(ruby: &Ruby, rb_self: &Self) -> Result<Value, Error> {
881
+ let array = ruby.ary_new_capa(rb_self.patterns.len());
882
+ for pattern in &rb_self.patterns {
883
+ array.push(ruby.str_new(pattern))?;
884
+ }
885
+ Ok(array.as_value())
886
+ }
887
+
888
+ fn additional(ruby: &Ruby, rb_self: &Self) -> Value {
889
+ ruby.obj_wrap(RbCanonicalSchema {
890
+ inner: rb_self.additional.clone(),
891
+ })
892
+ .as_value()
893
+ }
894
+
895
+ fn inspect(ruby: &Ruby, rb_self: &Self) -> Result<String, Error> {
896
+ Ok(format!(
897
+ "#<JSONSchema::Canonical::UndeclaredValueFailsView names={} patterns={} additional={}>",
898
+ Self::names(ruby, rb_self)?.inspect(),
899
+ Self::patterns(ruby, rb_self)?.inspect(),
900
+ Self::additional(ruby, rb_self).inspect()
901
+ ))
902
+ }
903
+
904
+ fn deconstruct_keys(ruby: &Ruby, rb_self: &Self, _keys: Value) -> Result<RHash, Error> {
905
+ let hash = ruby.hash_new();
906
+ hash.aset(ruby.sym_new("names"), Self::names(ruby, rb_self)?)?;
907
+ hash.aset(ruby.sym_new("patterns"), Self::patterns(ruby, rb_self)?)?;
908
+ hash.aset(ruby.sym_new("additional"), Self::additional(ruby, rb_self))?;
909
+ Ok(hash)
910
+ }
911
+ }
912
+
786
913
  /// An object value's constraints.
787
914
  #[derive(magnus::TypedData)]
788
915
  #[magnus(class = "JSONSchema::Canonical::ObjectView", free_immediately)]
@@ -794,6 +921,7 @@ pub struct ObjectView {
794
921
  properties: std::collections::BTreeMap<String, CanonicalSchema>,
795
922
  pattern_properties: std::collections::BTreeMap<String, CanonicalSchema>,
796
923
  additional_properties: Option<CanonicalSchema>,
924
+ violations: Vec<CoreObjectViolationView>,
797
925
  }
798
926
 
799
927
  impl DataTypeFunctions for ObjectView {}
@@ -859,6 +987,14 @@ impl ObjectView {
859
987
  }
860
988
  }
861
989
 
990
+ fn violations(ruby: &Ruby, rb_self: &Self) -> Result<Value, Error> {
991
+ let array = ruby.ary_new_capa(rb_self.violations.len());
992
+ for violation in &rb_self.violations {
993
+ array.push(object_violation_to_ruby(ruby, violation))?;
994
+ }
995
+ Ok(array.as_value())
996
+ }
997
+
862
998
  fn inspect(ruby: &Ruby, rb_self: &Self) -> Result<String, Error> {
863
999
  Ok(format!(
864
1000
  "#<JSONSchema::Canonical::ObjectView min_properties={} max_properties={} required={} property_names={} properties={} pattern_properties={}>",
@@ -895,6 +1031,7 @@ impl ObjectView {
895
1031
  ruby.sym_new("additional_properties"),
896
1032
  Self::additional_properties(ruby, rb_self),
897
1033
  )?;
1034
+ hash.aset(ruby.sym_new("violations"), Self::violations(ruby, rb_self)?)?;
898
1035
  Ok(hash)
899
1036
  }
900
1037
  }
@@ -1152,9 +1289,13 @@ fn canonicalize(ruby: &Ruby, args: &[Value]) -> Result<Value, Error> {
1152
1289
  *CANONICAL_KW_DRAFT,
1153
1290
  *CANONICAL_KW_VALIDATE_FORMATS,
1154
1291
  *CANONICAL_KW_PATTERN_OPTIONS,
1292
+ *KW_RETRIEVER,
1293
+ *KW_REGISTRY,
1294
+ *KW_BASE_URI,
1155
1295
  ],
1156
1296
  )?;
1157
- let (draft_val, validate_formats, pattern_options) = base_kwargs.optional;
1297
+ let (draft_val, validate_formats, pattern_options, retriever_val, registry_val, base_uri) =
1298
+ base_kwargs.optional;
1158
1299
 
1159
1300
  let schema_value = to_schema_value(ruby, schema_arg)?;
1160
1301
  let mut options = jsonschema::canonical::options();
@@ -1170,6 +1311,34 @@ fn canonicalize(ruby: &Ruby, args: &[Value]) -> Result<Value, Error> {
1170
1311
  RbPatternOptions::Regex(inner) => options = options.with_pattern_options(inner),
1171
1312
  }
1172
1313
  }
1314
+ let mut has_retriever = false;
1315
+ if let Some(val) = retriever_val {
1316
+ if let Some(retriever) = make_retriever(ruby, val)? {
1317
+ options = options.with_retriever(retriever);
1318
+ has_retriever = true;
1319
+ }
1320
+ }
1321
+ if let Some(val) = registry_val {
1322
+ if !val.is_nil() {
1323
+ let registry: &Registry = TryConvert::try_convert(val).map_err(|_| {
1324
+ Error::new(
1325
+ ruby.exception_type_error(),
1326
+ "registry must be a JSONSchema::Registry instance",
1327
+ )
1328
+ })?;
1329
+ if !has_retriever {
1330
+ if let Some(value) = registry.retriever_value(ruby) {
1331
+ if let Some(retriever) = make_retriever(ruby, value)? {
1332
+ options = options.with_retriever(retriever);
1333
+ }
1334
+ }
1335
+ }
1336
+ options = options.with_registry(registry.inner.as_ref());
1337
+ }
1338
+ }
1339
+ if let Some(base_uri) = base_uri {
1340
+ options = options.with_base_uri(base_uri);
1341
+ }
1173
1342
  options
1174
1343
  .canonicalize(&schema_value)
1175
1344
  .map(|inner| ruby.obj_wrap(RbCanonicalSchema { inner }).as_value())
@@ -1299,7 +1468,7 @@ pub(crate) fn init_canonical(ruby: &Ruby, module: &RModule) -> Result<(), Error>
1299
1468
  let array_view = canonical_module.define_class("ArrayView", ruby.class_object())?;
1300
1469
  array_view.define_method("min_items", method!(ArrayView::min_items, 0))?;
1301
1470
  array_view.define_method("max_items", method!(ArrayView::max_items, 0))?;
1302
- array_view.define_method("unique_items", method!(ArrayView::unique_items, 0))?;
1471
+ array_view.define_method("distinctness", method!(ArrayView::distinctness, 0))?;
1303
1472
  array_view.define_method("prefix_items", method!(ArrayView::prefix_items, 0))?;
1304
1473
  array_view.define_method("items", method!(ArrayView::items, 0))?;
1305
1474
  array_view.define_method("contains", method!(ArrayView::contains, 0))?;
@@ -1315,6 +1484,31 @@ pub(crate) fn init_canonical(ruby: &Ruby, module: &RModule) -> Result<(), Error>
1315
1484
  method!(ContainsView::deconstruct_keys, 1),
1316
1485
  )?;
1317
1486
 
1487
+ let name_fails_view = canonical_module.define_class("NameFailsView", ruby.class_object())?;
1488
+ name_fails_view.define_method("schema", method!(NameFailsView::schema, 0))?;
1489
+ name_fails_view.define_method("inspect", method!(NameFailsView::inspect, 0))?;
1490
+ name_fails_view.define_method(
1491
+ "deconstruct_keys",
1492
+ method!(NameFailsView::deconstruct_keys, 1),
1493
+ )?;
1494
+
1495
+ let undeclared_value_fails_view =
1496
+ canonical_module.define_class("UndeclaredValueFailsView", ruby.class_object())?;
1497
+ undeclared_value_fails_view
1498
+ .define_method("names", method!(UndeclaredValueFailsView::names, 0))?;
1499
+ undeclared_value_fails_view
1500
+ .define_method("patterns", method!(UndeclaredValueFailsView::patterns, 0))?;
1501
+ undeclared_value_fails_view.define_method(
1502
+ "additional",
1503
+ method!(UndeclaredValueFailsView::additional, 0),
1504
+ )?;
1505
+ undeclared_value_fails_view
1506
+ .define_method("inspect", method!(UndeclaredValueFailsView::inspect, 0))?;
1507
+ undeclared_value_fails_view.define_method(
1508
+ "deconstruct_keys",
1509
+ method!(UndeclaredValueFailsView::deconstruct_keys, 1),
1510
+ )?;
1511
+
1318
1512
  let object_view = canonical_module.define_class("ObjectView", ruby.class_object())?;
1319
1513
  object_view.define_method("min_properties", method!(ObjectView::min_properties, 0))?;
1320
1514
  object_view.define_method("max_properties", method!(ObjectView::max_properties, 0))?;
@@ -1329,6 +1523,7 @@ pub(crate) fn init_canonical(ruby: &Ruby, module: &RModule) -> Result<(), Error>
1329
1523
  "additional_properties",
1330
1524
  method!(ObjectView::additional_properties, 0),
1331
1525
  )?;
1526
+ object_view.define_method("violations", method!(ObjectView::violations, 0))?;
1332
1527
  object_view.define_method("inspect", method!(ObjectView::inspect, 0))?;
1333
1528
  object_view.define_method("deconstruct_keys", method!(ObjectView::deconstruct_keys, 1))?;
1334
1529
 
data/src/options.rs CHANGED
@@ -30,8 +30,8 @@ define_rb_intern!(static KW_DRAFT: "draft");
30
30
  define_rb_intern!(static KW_VALIDATE_FORMATS: "validate_formats");
31
31
  define_rb_intern!(static KW_IGNORE_UNKNOWN_FORMATS: "ignore_unknown_formats");
32
32
  define_rb_intern!(static KW_MASK: "mask");
33
- define_rb_intern!(static KW_BASE_URI: "base_uri");
34
- define_rb_intern!(static KW_RETRIEVER: "retriever");
33
+ define_rb_intern!(pub(crate) static KW_BASE_URI: "base_uri");
34
+ define_rb_intern!(pub(crate) static KW_RETRIEVER: "retriever");
35
35
  define_rb_intern!(static KW_FORMATS: "formats");
36
36
  define_rb_intern!(static KW_KEYWORDS: "keywords");
37
37
  define_rb_intern!(pub(crate) static KW_REGISTRY: "registry");
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.49.5
4
+ version: 0.49.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dmitry Dygalo