jsonschema_rs 0.49.0 → 0.49.3

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: 5089bd59db447c9dd706a0fcaf832dac6832d5be6662e988b7a386c8cd31e6b0
4
- data.tar.gz: ed3f7c83e18c5b8eea755a6a814106693ac729a11325946e878daca82afa0a32
3
+ metadata.gz: 48dc9cf6305e242c8a686a6e1439fcc2d05ce1b2738bfdf1eb42394e05f16d03
4
+ data.tar.gz: 9e828ed439bb3180094d3c2cdc1cbc0723ea71d385c2861278c7347493dfd900
5
5
  SHA512:
6
- metadata.gz: f15778547054d8aa3e988d34db28fa5144ed87821f4be792120366dc93ff3f2ae908f64610e72047f111f10617187ea6d0debd859be1cb5de11756af8bf874a0
7
- data.tar.gz: 5d9f288ab525665571492a9e6a8f7846b01dc07f78cee128a998777edcfcb2fb8977dcab97735c4bbbb1634f6f3e350904ec9c1d4e1d987de3c86fefc030f24b
6
+ metadata.gz: d41807f218f18e5435a4ec6e01326f5459076c78afd126844dcd03a982e1006514ec613333eac241853e8b83859410ab723f53ffa185f959cfd6209f8a4c6399
7
+ data.tar.gz: 768c332d2d735999f58bde2a4947568d9e4e7c7cbf818e6ed8ae4177d890810490cf2494b5bfcea547fe7a0c7827775ba83192e465f77207581a9e40d6d21f1f
data/CHANGELOG.md CHANGED
@@ -2,6 +2,49 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [0.49.3] - 2026-08-02
6
+
7
+ ### Added
8
+
9
+ - Canonicalization of a recursive schema with no finite witness, which now folds to `false`.
10
+ - 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`.
11
+ - Canonicalization of `minContains` under `uniqueItems`, where a demand asking for more matches than its own schema has distinct values now folds to `false`.
12
+ - Canonicalization of a Draft 4 `patternProperties` coverage closed by `additionalProperties: false`, spelled as the closed map it was parsed from.
13
+ - Canonicalization of a `oneOf` whose branches repeat, where a repeated branch can never contribute exactly one match.
14
+ - Canonicalization of a `$ref` whose target is an empty schema, which now folds to `false`.
15
+ - Canonicalization of `unevaluatedItems` beside `allOf`, where every branch must pass and so the indexes they evaluate are known without the instance.
16
+ - Canonicalization of `unevaluatedProperties` beside `allOf`, where every branch must pass and so what they evaluate is known without the instance.
17
+ - Canonicalization of a Draft 4 `type` list holding `integer` beside other types with `enum`, which previously modeled only when spelled as an `allOf`.
18
+ - Canonicalization of `patternProperties` patterns matching finitely many keys, such as `^a$` and `^(a|b)$`.
19
+ - Canonicalization of `unevaluatedProperties` and `unevaluatedItems` when no in-place applicator sits beside them.
20
+
21
+ ### Fixed
22
+
23
+ - `additionalItems` values that are not schemas silently ignored beside an array-form `items` (they should fail the build like `additionalProperties`).
24
+ - `additionalItems` beside a boolean `items` rejecting every instance, such as `{"additionalItems": false, "items": false}`.
25
+ - Draft 4 rejecting a size bound at or past `2^64`, such as `{"maxItems": 18446744073709551616}`.
26
+ - An integer past the `f64` range admitted by a fractional bound it exceeds, such as `1e400` under `{"exclusiveMaximum": 0.1}`.
27
+ - 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.
28
+ - Canonicalization reusing one definition's body for a same-named definition in another resource, when the name spells a canonical URI.
29
+ - `unevaluatedItems` counting `prefixItems` as evaluating elements before Draft 2020-12, where it is not a keyword.
30
+
31
+ ### Performance
32
+
33
+ - Up to 70% faster `evaluate`.
34
+
35
+ ## [0.49.2] - 2026-07-28
36
+
37
+ ### Performance
38
+
39
+ - Faster serialization of canonicalized schemas.
40
+
41
+ ## [0.49.1] - 2026-07-25
42
+
43
+ ### Fixed
44
+
45
+ - `JSONSchema.canonicalize` rejecting `pattern_options` (it should take the same regex configuration as validators).
46
+ - `InvalidPattern` failures raising the base `CanonicalizationError` (they should raise `JSONSchema::Canonical::InvalidPattern`).
47
+
5
48
  ## [0.49.0] - 2026-07-25
6
49
 
7
50
  ### Added
@@ -219,7 +262,10 @@
219
262
 
220
263
  - Initial public release
221
264
 
222
- [Unreleased]: https://github.com/Stranger6667/jsonschema/compare/ruby-v0.49.0...HEAD
265
+ [Unreleased]: https://github.com/Stranger6667/jsonschema/compare/ruby-v0.49.3...HEAD
266
+ [0.49.3]: https://github.com/Stranger6667/jsonschema/compare/ruby-v0.49.2...ruby-v0.49.3
267
+ [0.49.2]: https://github.com/Stranger6667/jsonschema/compare/ruby-v0.49.1...ruby-v0.49.2
268
+ [0.49.1]: https://github.com/Stranger6667/jsonschema/compare/ruby-v0.49.0...ruby-v0.49.1
223
269
  [0.49.0]: https://github.com/Stranger6667/jsonschema/compare/ruby-v0.48.5...ruby-v0.49.0
224
270
  [0.48.5]: https://github.com/Stranger6667/jsonschema/compare/ruby-v0.48.2...ruby-v0.48.5
225
271
  [0.48.2]: https://github.com/Stranger6667/jsonschema/compare/ruby-v0.48.1...ruby-v0.48.2
data/Cargo.toml CHANGED
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "jsonschema-rb"
3
- version = "0.49.0"
3
+ version = "0.49.3"
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.0", default-features = false, features = ["magnus", "arbitrary-precision", "resolve-http", "resolve-file", "tls-ring", "macros"] }
16
+ jsonschema = { version = "0.49.3", 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.0"
696
+ version = "0.49.3"
697
697
  source = "registry+https://github.com/rust-lang/crates.io-index"
698
- checksum = "9eb9cf6891f8d15a89f7bcf8e812a62efef1fd8d9e7e4522f455875a1224875a"
698
+ checksum = "508004a5500f2e1f68af048f70feea2de86d35ab115d85716530860822aef397"
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.0"
729
+ version = "0.49.3"
730
730
  source = "registry+https://github.com/rust-lang/crates.io-index"
731
- checksum = "78fac461293b8d5484a845adbbfaa263ae76616ceae93283baaa4621736f9c54"
731
+ checksum = "f4e131231bc18676df289bd7634d4353d5b36bced191928bfa2a2dcae91e44a0"
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.0"
739
+ version = "0.49.3"
740
740
  source = "registry+https://github.com/rust-lang/crates.io-index"
741
- checksum = "937a50f77ead02f355faec45d36f0b739da183857002af4f3a2759451dc9aec3"
741
+ checksum = "75803a5014f912d5a8f3c8cc24531d19ea06dfadda75ddf1d15af629f7c8468c"
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.0"
758
+ version = "0.49.3"
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.0"
771
+ version = "0.49.3"
772
772
  source = "registry+https://github.com/rust-lang/crates.io-index"
773
- checksum = "b70811da032e736899c5045ee30f069ba241676739e6ed042c1f9ddd3ad47cde"
773
+ checksum = "5a8b30cafa78358ae6cd1494a7d6410b89530e28bf567f862c869c667e900d9f"
774
774
  dependencies = [
775
775
  "regex-syntax",
776
776
  ]
777
777
 
778
778
  [[package]]
779
779
  name = "jsonschema-value"
780
- version = "0.49.0"
780
+ version = "0.49.3"
781
781
  source = "registry+https://github.com/rust-lang/crates.io-index"
782
- checksum = "5ceacf7ad8e9a1f6229a1354dc0ab238855623d219b6abf0a001c138241ec530"
782
+ checksum = "5526bd381d230af94908d07e6835a33fd82a465e12f5f1e9c81f5c2aa23b3c21"
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.0"
1135
+ version = "0.49.3"
1136
1136
  source = "registry+https://github.com/rust-lang/crates.io-index"
1137
- checksum = "cbded44c4882a15738bd1bba376609f679292d758c0b3c389a2ef4a0ea6ce9b7"
1137
+ checksum = "7af3eb523cce0df0af3c30d624b829b2dabd233172b5bc2615fcd03ceae8f746"
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.0"
3
+ version = "0.49.3"
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.0", default-features = false, features = ["magnus", "arbitrary-precision", "resolve-http", "resolve-file", "tls-ring", "macros"] }
13
+ jsonschema = { version = "0.49.3", 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.0"
16
+ referencing = "0.49.3"
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.0"
4
+ VERSION = "0.49.3"
5
5
  end
data/sig/jsonschema.rbs CHANGED
@@ -29,6 +29,9 @@ module JSONSchema
29
29
  class InvalidSchemaType < CanonicalizationError
30
30
  end
31
31
 
32
+ class InvalidPattern < CanonicalizationError
33
+ end
34
+
32
35
  # A schema reduced to canonical form: schemas accepting the same values share one form.
33
36
  class CanonicalSchema
34
37
  def to_json_schema: () -> untyped
@@ -164,7 +167,8 @@ module JSONSchema
164
167
  def self.canonicalize: (
165
168
  untyped schema,
166
169
  ?draft: draft?,
167
- ?validate_formats: bool?
170
+ ?validate_formats: bool?,
171
+ ?pattern_options: (RegexOptions | FancyRegexOptions)?
168
172
  ) -> Canonical::CanonicalSchema
169
173
 
170
174
  # Create a validator with auto-detected draft version.
data/src/canonical.rs CHANGED
@@ -14,13 +14,17 @@ use magnus::{
14
14
  };
15
15
 
16
16
  use crate::{
17
- options::parse_draft_symbol,
17
+ options::{extract_pattern_options, parse_draft_symbol, RbPatternOptions},
18
18
  ser::{to_schema_value, value_to_ruby},
19
19
  static_id::define_rb_intern,
20
20
  };
21
21
 
22
22
  define_rb_intern!(static CANONICAL_KW_DRAFT: "draft");
23
23
  define_rb_intern!(static CANONICAL_KW_VALIDATE_FORMATS: "validate_formats");
24
+ define_rb_intern!(static CANONICAL_KW_PATTERN_OPTIONS: "pattern_options");
25
+
26
+ type CanonicalKwArgs =
27
+ magnus::scan_args::KwArgs<(), (Option<Value>, Option<bool>, Option<Value>), ()>;
24
28
 
25
29
  macro_rules! canonical_error_class {
26
30
  ($static_name:ident, $class_name:literal) => {
@@ -42,6 +46,7 @@ macro_rules! canonical_error_class {
42
46
 
43
47
  canonical_error_class!(CANONICALIZATION_ERROR_CLASS, "CanonicalizationError");
44
48
  canonical_error_class!(INVALID_SCHEMA_TYPE_CLASS, "InvalidSchemaType");
49
+ canonical_error_class!(INVALID_PATTERN_CLASS, "InvalidPattern");
45
50
 
46
51
  fn canonicalization_error(ruby: &Ruby, error: CanonicalizationError) -> Error {
47
52
  if let CanonicalizationError::ValidationError(validation_error) = error {
@@ -52,6 +57,9 @@ fn canonicalization_error(ruby: &Ruby, error: CanonicalizationError) -> Error {
52
57
  CanonicalizationError::InvalidSchemaType(_) => {
53
58
  Error::new(ruby.get_inner(&INVALID_SCHEMA_TYPE_CLASS), message)
54
59
  }
60
+ CanonicalizationError::InvalidPattern { .. } => {
61
+ Error::new(ruby.get_inner(&INVALID_PATTERN_CLASS), message)
62
+ }
55
63
  // `ValidationError` returns above; future variants fall back to the base canonical error.
56
64
  _ => Error::new(ruby.get_inner(&CANONICALIZATION_ERROR_CLASS), message),
57
65
  }
@@ -174,7 +182,11 @@ impl RbCanonicalSchema {
174
182
  additional_properties: view.additional_properties,
175
183
  })
176
184
  .as_value(),
185
+ CanonicalView::Not(schema) => ruby.obj_wrap(NotView { schema: *schema }).as_value(),
186
+ CanonicalView::AllOf(branches) => ruby.obj_wrap(AllOfView { branches }).as_value(),
177
187
  CanonicalView::AnyOf(branches) => ruby.obj_wrap(AnyOfView { branches }).as_value(),
188
+ CanonicalView::OneOf(branches) => ruby.obj_wrap(OneOfView { branches }).as_value(),
189
+ CanonicalView::Reference(uri) => ruby.obj_wrap(ReferenceView { uri }).as_value(),
178
190
  CanonicalView::Raw(schema) => ruby.obj_wrap(RawView { schema }).as_value(),
179
191
  }
180
192
  }
@@ -828,6 +840,147 @@ impl AnyOfView {
828
840
  }
829
841
  }
830
842
 
843
+ /// A value matches iff exactly one branch matches.
844
+ #[derive(magnus::TypedData)]
845
+ #[magnus(class = "JSONSchema::Canonical::OneOfView", free_immediately)]
846
+ pub struct OneOfView {
847
+ branches: Vec<CanonicalSchema>,
848
+ }
849
+
850
+ impl DataTypeFunctions for OneOfView {}
851
+
852
+ impl OneOfView {
853
+ fn branches(ruby: &Ruby, rb_self: &Self) -> Result<Value, Error> {
854
+ let array = ruby.ary_new_capa(rb_self.branches.len());
855
+ for branch in &rb_self.branches {
856
+ array.push(
857
+ ruby.obj_wrap(RbCanonicalSchema {
858
+ inner: branch.clone(),
859
+ })
860
+ .as_value(),
861
+ )?;
862
+ }
863
+ Ok(array.as_value())
864
+ }
865
+
866
+ fn inspect(ruby: &Ruby, rb_self: &Self) -> Result<String, Error> {
867
+ let kinds = ruby.ary_new_capa(rb_self.branches.len());
868
+ for branch in &rb_self.branches {
869
+ kinds.push(ruby.sym_new(branch.kind().as_str()).as_value())?;
870
+ }
871
+ Ok(format!(
872
+ "#<JSONSchema::Canonical::OneOfView branches={}>",
873
+ kinds.as_value().inspect()
874
+ ))
875
+ }
876
+
877
+ fn deconstruct_keys(ruby: &Ruby, rb_self: &Self, _keys: Value) -> Result<RHash, Error> {
878
+ let hash = ruby.hash_new();
879
+ hash.aset(ruby.sym_new("branches"), Self::branches(ruby, rb_self)?)?;
880
+ Ok(hash)
881
+ }
882
+ }
883
+
884
+ /// A value matches iff every branch matches.
885
+ #[derive(magnus::TypedData)]
886
+ #[magnus(class = "JSONSchema::Canonical::AllOfView", free_immediately)]
887
+ pub struct AllOfView {
888
+ branches: Vec<CanonicalSchema>,
889
+ }
890
+
891
+ impl DataTypeFunctions for AllOfView {}
892
+
893
+ impl AllOfView {
894
+ fn branches(ruby: &Ruby, rb_self: &Self) -> Result<Value, Error> {
895
+ let array = ruby.ary_new_capa(rb_self.branches.len());
896
+ for branch in &rb_self.branches {
897
+ array.push(
898
+ ruby.obj_wrap(RbCanonicalSchema {
899
+ inner: branch.clone(),
900
+ })
901
+ .as_value(),
902
+ )?;
903
+ }
904
+ Ok(array.as_value())
905
+ }
906
+
907
+ fn inspect(ruby: &Ruby, rb_self: &Self) -> Result<String, Error> {
908
+ let kinds = ruby.ary_new_capa(rb_self.branches.len());
909
+ for branch in &rb_self.branches {
910
+ kinds.push(ruby.sym_new(branch.kind().as_str()).as_value())?;
911
+ }
912
+ Ok(format!(
913
+ "#<JSONSchema::Canonical::AllOfView branches={}>",
914
+ kinds.as_value().inspect()
915
+ ))
916
+ }
917
+
918
+ fn deconstruct_keys(ruby: &Ruby, rb_self: &Self, _keys: Value) -> Result<RHash, Error> {
919
+ let hash = ruby.hash_new();
920
+ hash.aset(ruby.sym_new("branches"), Self::branches(ruby, rb_self)?)?;
921
+ Ok(hash)
922
+ }
923
+ }
924
+
925
+ /// The complement of `schema`, preserving a symbolic ref under `not`, conditionals, and `oneOf`.
926
+ #[derive(magnus::TypedData)]
927
+ #[magnus(class = "JSONSchema::Canonical::NotView", free_immediately)]
928
+ pub struct NotView {
929
+ schema: CanonicalSchema,
930
+ }
931
+
932
+ impl DataTypeFunctions for NotView {}
933
+
934
+ impl NotView {
935
+ fn schema(ruby: &Ruby, rb_self: &Self) -> Value {
936
+ ruby.obj_wrap(RbCanonicalSchema {
937
+ inner: rb_self.schema.clone(),
938
+ })
939
+ .as_value()
940
+ }
941
+
942
+ fn inspect(rb_self: &Self) -> String {
943
+ format!(
944
+ "#<JSONSchema::Canonical::NotView schema={}>",
945
+ rb_self.schema.kind().as_str()
946
+ )
947
+ }
948
+
949
+ fn deconstruct_keys(ruby: &Ruby, rb_self: &Self, _keys: Value) -> Result<RHash, Error> {
950
+ let hash = ruby.hash_new();
951
+ hash.aset(ruby.sym_new("schema"), Self::schema(ruby, rb_self))?;
952
+ Ok(hash)
953
+ }
954
+ }
955
+
956
+ /// A symbolic JSON Schema reference.
957
+ #[derive(magnus::TypedData)]
958
+ #[magnus(class = "JSONSchema::Canonical::ReferenceView", free_immediately)]
959
+ pub struct ReferenceView {
960
+ uri: String,
961
+ }
962
+
963
+ impl DataTypeFunctions for ReferenceView {}
964
+
965
+ impl ReferenceView {
966
+ fn uri(rb_self: &Self) -> String {
967
+ rb_self.uri.clone()
968
+ }
969
+
970
+ fn inspect(rb_self: &Self) -> String {
971
+ format!(
972
+ "#<JSONSchema::Canonical::ReferenceView uri={:?}>",
973
+ rb_self.uri
974
+ )
975
+ }
976
+
977
+ fn deconstruct_keys(ruby: &Ruby, rb_self: &Self, _keys: Value) -> Result<RHash, Error> {
978
+ let hash = ruby.hash_new();
979
+ hash.aset(ruby.sym_new("uri"), rb_self.uri.clone())?;
980
+ Ok(hash)
981
+ }
982
+ }
983
+
831
984
  /// Exactly one admitted value.
832
985
  #[derive(magnus::TypedData)]
833
986
  #[magnus(class = "JSONSchema::Canonical::ConstView", free_immediately)]
@@ -892,12 +1045,16 @@ fn canonicalize(ruby: &Ruby, args: &[Value]) -> Result<Value, Error> {
892
1045
  let parsed = scan_args::<(Value,), (), (), (), _, ()>(args)?;
893
1046
  let (schema_arg,) = parsed.required;
894
1047
  let keywords: RHash = parsed.keywords;
895
- let base_kwargs: magnus::scan_args::KwArgs<(), (Option<Value>, Option<bool>), ()> = get_kwargs(
1048
+ let base_kwargs: CanonicalKwArgs = get_kwargs(
896
1049
  keywords,
897
1050
  &[],
898
- &[*CANONICAL_KW_DRAFT, *CANONICAL_KW_VALIDATE_FORMATS],
1051
+ &[
1052
+ *CANONICAL_KW_DRAFT,
1053
+ *CANONICAL_KW_VALIDATE_FORMATS,
1054
+ *CANONICAL_KW_PATTERN_OPTIONS,
1055
+ ],
899
1056
  )?;
900
- let (draft_val, validate_formats) = base_kwargs.optional;
1057
+ let (draft_val, validate_formats, pattern_options) = base_kwargs.optional;
901
1058
 
902
1059
  let schema_value = to_schema_value(ruby, schema_arg)?;
903
1060
  let mut options = jsonschema::canonical::options();
@@ -907,6 +1064,12 @@ fn canonicalize(ruby: &Ruby, args: &[Value]) -> Result<Value, Error> {
907
1064
  if let Some(validate_formats) = validate_formats {
908
1065
  options = options.should_validate_formats(validate_formats);
909
1066
  }
1067
+ if let Some(val) = pattern_options {
1068
+ match extract_pattern_options(ruby, val)? {
1069
+ RbPatternOptions::Fancy(inner) => options = options.with_pattern_options(inner),
1070
+ RbPatternOptions::Regex(inner) => options = options.with_pattern_options(inner),
1071
+ }
1072
+ }
910
1073
  options
911
1074
  .canonicalize(&schema_value)
912
1075
  .map(|inner| ruby.obj_wrap(RbCanonicalSchema { inner }).as_value())
@@ -919,6 +1082,7 @@ pub(crate) fn init_canonical(ruby: &Ruby, module: &RModule) -> Result<(), Error>
919
1082
  let base_error =
920
1083
  canonical_module.define_error("CanonicalizationError", ruby.exception_standard_error())?;
921
1084
  canonical_module.define_error("InvalidSchemaType", base_error)?;
1085
+ canonical_module.define_error("InvalidPattern", base_error)?;
922
1086
 
923
1087
  let canonical_schema = canonical_module.define_class("CanonicalSchema", ruby.class_object())?;
924
1088
  canonical_schema.define_method(
@@ -1055,6 +1219,29 @@ pub(crate) fn init_canonical(ruby: &Ruby, module: &RModule) -> Result<(), Error>
1055
1219
  any_of_view.define_method("inspect", method!(AnyOfView::inspect, 0))?;
1056
1220
  any_of_view.define_method("deconstruct_keys", method!(AnyOfView::deconstruct_keys, 1))?;
1057
1221
 
1222
+ let one_of_view = canonical_module.define_class("OneOfView", ruby.class_object())?;
1223
+ one_of_view.define_method("branches", method!(OneOfView::branches, 0))?;
1224
+ one_of_view.define_method("inspect", method!(OneOfView::inspect, 0))?;
1225
+ one_of_view.define_method("deconstruct_keys", method!(OneOfView::deconstruct_keys, 1))?;
1226
+
1227
+ let all_of_view = canonical_module.define_class("AllOfView", ruby.class_object())?;
1228
+ all_of_view.define_method("branches", method!(AllOfView::branches, 0))?;
1229
+ all_of_view.define_method("inspect", method!(AllOfView::inspect, 0))?;
1230
+ all_of_view.define_method("deconstruct_keys", method!(AllOfView::deconstruct_keys, 1))?;
1231
+
1232
+ let not_view = canonical_module.define_class("NotView", ruby.class_object())?;
1233
+ not_view.define_method("schema", method!(NotView::schema, 0))?;
1234
+ not_view.define_method("inspect", method!(NotView::inspect, 0))?;
1235
+ not_view.define_method("deconstruct_keys", method!(NotView::deconstruct_keys, 1))?;
1236
+
1237
+ let reference_view = canonical_module.define_class("ReferenceView", ruby.class_object())?;
1238
+ reference_view.define_method("uri", method!(ReferenceView::uri, 0))?;
1239
+ reference_view.define_method("inspect", method!(ReferenceView::inspect, 0))?;
1240
+ reference_view.define_method(
1241
+ "deconstruct_keys",
1242
+ method!(ReferenceView::deconstruct_keys, 1),
1243
+ )?;
1244
+
1058
1245
  let raw_view = canonical_module.define_class("RawView", ruby.class_object())?;
1059
1246
  raw_view.define_method("schema", method!(RawView::schema, 0))?;
1060
1247
  raw_view.define_method("inspect", method!(RawView::inspect, 0))?;
data/src/options.rs CHANGED
@@ -741,32 +741,9 @@ pub fn make_options_from_kwargs(
741
741
  }
742
742
 
743
743
  if let Some(val) = pattern_options_val {
744
- if let Ok(fancy_opts) = <&FancyRegexOptions>::try_convert(val) {
745
- let mut po = jsonschema::PatternOptions::fancy_regex();
746
- if let Some(limit) = fancy_opts.backtrack_limit {
747
- po = po.backtrack_limit(limit);
748
- }
749
- if let Some(limit) = fancy_opts.size_limit {
750
- po = po.size_limit(limit);
751
- }
752
- if let Some(limit) = fancy_opts.dfa_size_limit {
753
- po = po.dfa_size_limit(limit);
754
- }
755
- opts = opts.with_pattern_options(po);
756
- } else if let Ok(regex_opts) = <&RegexOptions>::try_convert(val) {
757
- let mut po = jsonschema::PatternOptions::regex();
758
- if let Some(limit) = regex_opts.size_limit {
759
- po = po.size_limit(limit);
760
- }
761
- if let Some(limit) = regex_opts.dfa_size_limit {
762
- po = po.dfa_size_limit(limit);
763
- }
764
- opts = opts.with_pattern_options(po);
765
- } else {
766
- return Err(Error::new(
767
- ruby.exception_type_error(),
768
- "pattern_options must be a RegexOptions or FancyRegexOptions instance",
769
- ));
744
+ match extract_pattern_options(ruby, val)? {
745
+ RbPatternOptions::Fancy(inner) => opts = opts.with_pattern_options(inner),
746
+ RbPatternOptions::Regex(inner) => opts = opts.with_pattern_options(inner),
770
747
  }
771
748
  }
772
749
 
@@ -953,6 +930,42 @@ impl RegexOptions {
953
930
  }
954
931
  }
955
932
 
933
+ /// A `pattern_options` argument converted into [`jsonschema::PatternOptions`].
934
+ pub(crate) enum RbPatternOptions {
935
+ Fancy(jsonschema::PatternOptions<jsonschema::FancyRegex>),
936
+ Regex(jsonschema::PatternOptions<jsonschema::Regex>),
937
+ }
938
+
939
+ pub(crate) fn extract_pattern_options(ruby: &Ruby, val: Value) -> Result<RbPatternOptions, Error> {
940
+ if let Ok(fancy_opts) = <&FancyRegexOptions>::try_convert(val) {
941
+ let mut po = jsonschema::PatternOptions::fancy_regex();
942
+ if let Some(limit) = fancy_opts.backtrack_limit {
943
+ po = po.backtrack_limit(limit);
944
+ }
945
+ if let Some(limit) = fancy_opts.size_limit {
946
+ po = po.size_limit(limit);
947
+ }
948
+ if let Some(limit) = fancy_opts.dfa_size_limit {
949
+ po = po.dfa_size_limit(limit);
950
+ }
951
+ Ok(RbPatternOptions::Fancy(po))
952
+ } else if let Ok(regex_opts) = <&RegexOptions>::try_convert(val) {
953
+ let mut po = jsonschema::PatternOptions::regex();
954
+ if let Some(limit) = regex_opts.size_limit {
955
+ po = po.size_limit(limit);
956
+ }
957
+ if let Some(limit) = regex_opts.dfa_size_limit {
958
+ po = po.dfa_size_limit(limit);
959
+ }
960
+ Ok(RbPatternOptions::Regex(po))
961
+ } else {
962
+ Err(Error::new(
963
+ ruby.exception_type_error(),
964
+ "pattern_options must be a RegexOptions or FancyRegexOptions instance",
965
+ ))
966
+ }
967
+ }
968
+
956
969
  #[magnus::wrap(class = "JSONSchema::FancyRegexOptions", free_immediately, size)]
957
970
  pub struct FancyRegexOptions {
958
971
  pub backtrack_limit: Option<usize>,
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.0
4
+ version: 0.49.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dmitry Dygalo