Class: Ruby::Rego::Builtins::Codecs::JsonSchema::Matcher
- Inherits:
-
Object
- Object
- Ruby::Rego::Builtins::Codecs::JsonSchema::Matcher
- Defined in:
- lib/ruby/rego/builtins/codecs/json_schema_match.rb
Overview
A pure-boolean document validator. Holds the root schema for $ref resolution and a per-ref
visited set keyed by [ref, document object id] so a self-referential schema validating a
non-shrinking document terminates instead of looping.
rubocop:disable Metrics/ClassLength
Constant Summary collapse
- MAX_DEPTH =
Validation recurses through
matches?(document drill-down, $ref-following, allOf/anyOf nesting) andcanonical(enum/const/uniqueItems equality). Both are bounded here so a pathologically deep document or schema returns undefined instead of a SystemStackError that would abort the whole policy (only BuiltinArgumentError is rescued by the registry). The bound matches JSON.parse’s default max_nesting (100) already enforced on the string-document path, keeping the raw-input and string-input paths consistent. gojsonschema validates deeper (to roughly 6000) before it too stack-overflows; documents nested past this bound are a documented divergence (undefined vs OPA’s true/false) rather than a crash in either tool. 100- TOO_DEEP =
Sentinel thrown past the recursion and caught at the
matchentry point. :__match_schema_too_deep__
Instance Method Summary collapse
-
#initialize(root) ⇒ Matcher
constructor
A new instance of Matcher.
-
#matches?(document, schema) ⇒ Boolean
rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/AbcSize Whether
documentvalidates againstschema(a subschema of the root). -
#re2_matches?(pattern, string) ⇒ Boolean
An unanchored RE2 match of
pattern(apatternkeyword orpatternPropertieskey) againststring, compiling each distinct pattern at most once per match call. -
#with_depth ⇒ Object
Bound one level of recursion; throw TOO_DEEP past the whole walk when the limit is exceeded.
Constructor Details
Instance Method Details
#matches?(document, schema) ⇒ Boolean
rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/AbcSize
Whether document validates against schema (a subschema of the root). Applies every keyword
gojsonschema knows; the document matches only when all applicable keywords are satisfied.
:reek:TooManyStatements
126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
# File 'lib/ruby/rego/builtins/codecs/json_schema_match.rb', line 126 def matches?(document, schema) return schema unless schema.is_a?(Hash) # a boolean schema matches all (true) / nothing (false) with_depth do ref = schema["$ref"] next ref_matches?(document, schema, ref) if ref.is_a?(String) type_ok?(document, schema["type"]) && enum_ok?(document, schema) && const_ok?(document, schema) && number_ok?(document, schema) && string_ok?(document, schema) && array_ok?(document, schema) && object_ok?(document, schema) && logic_ok?(document, schema) && format_ok?(document, schema) end end |
#re2_matches?(pattern, string) ⇒ Boolean
An unanchored RE2 match of pattern (a pattern keyword or patternProperties key) against
string, compiling each distinct pattern at most once per match call. patternProperties tests
every schema pattern against every document property name (N x M), so without this cache the
gem would recompile N x M times — a CPU amplification on a valid schema+document. A compiled
regex (or nil, for an unusable pattern) is memoised by pattern string for the call’s lifetime.
:reek:NilCheck
105 106 107 108 109 110 |
# File 'lib/ruby/rego/builtins/codecs/json_schema_match.rb', line 105 def re2_matches?(pattern, string) return false unless string.is_a?(String) && string.valid_encoding? regex = @re2_cache.fetch(pattern) { @re2_cache[pattern] = JsonSchema.re2_compile(pattern) } regex ? regex.match?(string) : false end |
#with_depth ⇒ Object
Bound one level of recursion; throw TOO_DEEP past the whole walk when the limit is exceeded.
113 114 115 116 117 118 119 120 |
# File 'lib/ruby/rego/builtins/codecs/json_schema_match.rb', line 113 def with_depth @depth += 1 throw TOO_DEEP, TOO_DEEP if @depth > MAX_DEPTH yield ensure @depth -= 1 end |