schemurai 3.1.0-aarch64-linux-gnu
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 +7 -0
- data/LICENSE +21 -0
- data/README.md +395 -0
- data/lib/schemurai/backend.rb +34 -0
- data/lib/schemurai/container_checks/array_diagnostics.rb +119 -0
- data/lib/schemurai/container_checks/object_diagnostics.rb +152 -0
- data/lib/schemurai/container_checks.rb +534 -0
- data/lib/schemurai/decimal.rb +11 -0
- data/lib/schemurai/dialect.rb +106 -0
- data/lib/schemurai/dialect_keywords.rb +91 -0
- data/lib/schemurai/dialects/draft2019_09.rb +27 -0
- data/lib/schemurai/dialects/draft2020_12.rb +27 -0
- data/lib/schemurai/dialects/draft7.rb +27 -0
- data/lib/schemurai/ecma_regexp.rb +46 -0
- data/lib/schemurai/error_message.rb +102 -0
- data/lib/schemurai/evaluation.rb +63 -0
- data/lib/schemurai/evaluation_limits.rb +65 -0
- data/lib/schemurai/evaluation_pool.rb +66 -0
- data/lib/schemurai/evaluator.rb +861 -0
- data/lib/schemurai/formats.rb +403 -0
- data/lib/schemurai/json_pointer.rb +11 -0
- data/lib/schemurai/limit_budget.rb +78 -0
- data/lib/schemurai/limit_exceeded.rb +18 -0
- data/lib/schemurai/limited_evaluator.rb +43 -0
- data/lib/schemurai/meta_schemas/draft2019_09.rb +149 -0
- data/lib/schemurai/meta_schemas/draft2020_12.rb +149 -0
- data/lib/schemurai/meta_schemas/draft7.rb +121 -0
- data/lib/schemurai/meta_schemas.rb +28 -0
- data/lib/schemurai/native/4.0/schemurai_native.so +0 -0
- data/lib/schemurai/native/diagnostics.rb +53 -0
- data/lib/schemurai/native/evaluator.rb +87 -0
- data/lib/schemurai/native/null_numeric.rb +23 -0
- data/lib/schemurai/number_checks.rb +128 -0
- data/lib/schemurai/schema_domain.rb +95 -0
- data/lib/schemurai/schema_graph.rb +538 -0
- data/lib/schemurai/schema_node.rb +55 -0
- data/lib/schemurai/string_checks.rb +166 -0
- data/lib/schemurai/type_checks.rb +59 -0
- data/lib/schemurai/unique_items.rb +68 -0
- data/lib/schemurai/value_equality.rb +72 -0
- data/lib/schemurai/version.rb +6 -0
- data/lib/schemurai/vm/compiler.rb +410 -0
- data/lib/schemurai/vm/evaluator.rb +663 -0
- data/lib/schemurai/vm/limited_evaluator.rb +27 -0
- data/lib/schemurai.rb +307 -0
- data/lib/schemurai_native.rb +4 -0
- data/sig/schemurai.rbs +108 -0
- metadata +121 -0
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../meta_schemas"
|
|
4
|
+
|
|
5
|
+
module Schemurai
|
|
6
|
+
module Internal
|
|
7
|
+
module MetaSchemas
|
|
8
|
+
module Draft201909
|
|
9
|
+
META_SCHEMA_URI = "https://json-schema.org/draft/2019-09/schema"
|
|
10
|
+
SCHEMA = {
|
|
11
|
+
"$schema" => META_SCHEMA_URI,
|
|
12
|
+
"$id" => META_SCHEMA_URI,
|
|
13
|
+
"$recursiveAnchor" => true,
|
|
14
|
+
"type" => ["object", "boolean"],
|
|
15
|
+
"properties" => {
|
|
16
|
+
"$id" => {"type" => "string"},
|
|
17
|
+
"$schema" => {"type" => "string"},
|
|
18
|
+
"$ref" => {"type" => "string"},
|
|
19
|
+
"$anchor" => {"type" => "string", "pattern" => "^[A-Za-z][-A-Za-z0-9.:_]*$"},
|
|
20
|
+
"$recursiveRef" => {"type" => "string"},
|
|
21
|
+
"$recursiveAnchor" => {"type" => "boolean"},
|
|
22
|
+
"$vocabulary" => {"type" => "object", "additionalProperties" => {"type" => "boolean"}},
|
|
23
|
+
"$comment" => {"type" => "string"},
|
|
24
|
+
"$defs" => {"type" => "object", "additionalProperties" => {"$recursiveRef" => "#"}},
|
|
25
|
+
"definitions" => {"type" => "object", "additionalProperties" => {"$recursiveRef" => "#"}},
|
|
26
|
+
"items" => {
|
|
27
|
+
"anyOf" => [
|
|
28
|
+
{"$recursiveRef" => "#"},
|
|
29
|
+
{"type" => "array", "minItems" => 1, "items" => {"$recursiveRef" => "#"}}
|
|
30
|
+
]
|
|
31
|
+
},
|
|
32
|
+
"additionalItems" => {"$recursiveRef" => "#"},
|
|
33
|
+
"contains" => {"$recursiveRef" => "#"},
|
|
34
|
+
"additionalProperties" => {"$recursiveRef" => "#"},
|
|
35
|
+
"unevaluatedItems" => {"$recursiveRef" => "#"},
|
|
36
|
+
"unevaluatedProperties" => {"$recursiveRef" => "#"},
|
|
37
|
+
"properties" => {"type" => "object", "additionalProperties" => {"$recursiveRef" => "#"}},
|
|
38
|
+
"patternProperties" => {"type" => "object", "additionalProperties" => {"$recursiveRef" => "#"}},
|
|
39
|
+
"dependentSchemas" => {"type" => "object", "additionalProperties" => {"$recursiveRef" => "#"}},
|
|
40
|
+
"dependencies" => {
|
|
41
|
+
"type" => "object",
|
|
42
|
+
"additionalProperties" => {
|
|
43
|
+
"anyOf" => [
|
|
44
|
+
{"$recursiveRef" => "#"},
|
|
45
|
+
{"type" => "array", "items" => {"type" => "string"}, "uniqueItems" => true}
|
|
46
|
+
]
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
"propertyNames" => {"$recursiveRef" => "#"},
|
|
50
|
+
"if" => {"$recursiveRef" => "#"},
|
|
51
|
+
"then" => {"$recursiveRef" => "#"},
|
|
52
|
+
"else" => {"$recursiveRef" => "#"},
|
|
53
|
+
"allOf" => {"type" => "array", "minItems" => 1, "items" => {"$recursiveRef" => "#"}},
|
|
54
|
+
"anyOf" => {"type" => "array", "minItems" => 1, "items" => {"$recursiveRef" => "#"}},
|
|
55
|
+
"oneOf" => {"type" => "array", "minItems" => 1, "items" => {"$recursiveRef" => "#"}},
|
|
56
|
+
"not" => {"$recursiveRef" => "#"},
|
|
57
|
+
"type" => {
|
|
58
|
+
"anyOf" => [
|
|
59
|
+
{"enum" => ["null", "boolean", "object", "array", "number", "integer", "string"]},
|
|
60
|
+
{
|
|
61
|
+
"type" => "array",
|
|
62
|
+
"items" => {"enum" => ["null", "boolean", "object", "array", "number", "integer", "string"]},
|
|
63
|
+
"minItems" => 1,
|
|
64
|
+
"uniqueItems" => true
|
|
65
|
+
}
|
|
66
|
+
]
|
|
67
|
+
},
|
|
68
|
+
"enum" => {"type" => "array"},
|
|
69
|
+
"multipleOf" => {"type" => "number", "exclusiveMinimum" => 0},
|
|
70
|
+
"maximum" => {"type" => "number"},
|
|
71
|
+
"exclusiveMaximum" => {"type" => "number"},
|
|
72
|
+
"minimum" => {"type" => "number"},
|
|
73
|
+
"exclusiveMinimum" => {"type" => "number"},
|
|
74
|
+
"minLength" => {"type" => "integer", "minimum" => 0},
|
|
75
|
+
"maxLength" => {"type" => "integer", "minimum" => 0},
|
|
76
|
+
"pattern" => {"type" => "string"},
|
|
77
|
+
"minItems" => {"type" => "integer", "minimum" => 0},
|
|
78
|
+
"maxItems" => {"type" => "integer", "minimum" => 0},
|
|
79
|
+
"uniqueItems" => {"type" => "boolean"},
|
|
80
|
+
"minContains" => {"type" => "integer", "minimum" => 0},
|
|
81
|
+
"maxContains" => {"type" => "integer", "minimum" => 0},
|
|
82
|
+
"minProperties" => {"type" => "integer", "minimum" => 0},
|
|
83
|
+
"maxProperties" => {"type" => "integer", "minimum" => 0},
|
|
84
|
+
"required" => {
|
|
85
|
+
"type" => "array",
|
|
86
|
+
"items" => {"type" => "string"},
|
|
87
|
+
"uniqueItems" => true
|
|
88
|
+
},
|
|
89
|
+
"dependentRequired" => {
|
|
90
|
+
"type" => "object",
|
|
91
|
+
"additionalProperties" => {
|
|
92
|
+
"type" => "array",
|
|
93
|
+
"items" => {"type" => "string"},
|
|
94
|
+
"uniqueItems" => true
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
"title" => {"type" => "string"},
|
|
98
|
+
"description" => {"type" => "string"},
|
|
99
|
+
"deprecated" => {"type" => "boolean"},
|
|
100
|
+
"readOnly" => {"type" => "boolean"},
|
|
101
|
+
"writeOnly" => {"type" => "boolean"},
|
|
102
|
+
"examples" => {"type" => "array"},
|
|
103
|
+
"format" => {"type" => "string"},
|
|
104
|
+
"contentEncoding" => {"type" => "string"},
|
|
105
|
+
"contentMediaType" => {"type" => "string"},
|
|
106
|
+
"contentSchema" => {"$recursiveRef" => "#"}
|
|
107
|
+
}
|
|
108
|
+
}.freeze
|
|
109
|
+
|
|
110
|
+
MetaSchemas.register(META_SCHEMA_URI, SCHEMA)
|
|
111
|
+
|
|
112
|
+
COMPONENT_KEYWORDS = {
|
|
113
|
+
"core" => %w[
|
|
114
|
+
$id $schema $ref $anchor $recursiveRef $recursiveAnchor $vocabulary $comment $defs
|
|
115
|
+
],
|
|
116
|
+
"applicator" => %w[
|
|
117
|
+
additionalItems unevaluatedItems items contains additionalProperties
|
|
118
|
+
unevaluatedProperties properties patternProperties dependentSchemas propertyNames
|
|
119
|
+
if then else allOf anyOf oneOf not
|
|
120
|
+
],
|
|
121
|
+
"validation" => %w[
|
|
122
|
+
type const enum multipleOf maximum exclusiveMaximum minimum exclusiveMinimum
|
|
123
|
+
maxLength minLength pattern maxItems minItems uniqueItems maxContains minContains
|
|
124
|
+
maxProperties minProperties required dependentRequired
|
|
125
|
+
],
|
|
126
|
+
"meta-data" => %w[title description default deprecated readOnly writeOnly examples],
|
|
127
|
+
"format" => %w[format],
|
|
128
|
+
"content" => %w[contentEncoding contentMediaType contentSchema]
|
|
129
|
+
}.freeze
|
|
130
|
+
|
|
131
|
+
COMPONENT_KEYWORDS.each do |name, keywords|
|
|
132
|
+
uri = "https://json-schema.org/draft/2019-09/meta/#{name}"
|
|
133
|
+
component = {
|
|
134
|
+
"$schema" => META_SCHEMA_URI,
|
|
135
|
+
"$id" => uri,
|
|
136
|
+
"$recursiveAnchor" => true,
|
|
137
|
+
"type" => ["object", "boolean"],
|
|
138
|
+
"properties" => SCHEMA.fetch("properties").slice(*keywords)
|
|
139
|
+
}.freeze
|
|
140
|
+
MetaSchemas.register(uri, component)
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
private_constant :META_SCHEMA_URI, :SCHEMA, :COMPONENT_KEYWORDS
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
private_constant :Internal
|
|
149
|
+
end
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../meta_schemas"
|
|
4
|
+
|
|
5
|
+
module Schemurai
|
|
6
|
+
module Internal
|
|
7
|
+
module MetaSchemas
|
|
8
|
+
module Draft202012
|
|
9
|
+
META_SCHEMA_URI = "https://json-schema.org/draft/2020-12/schema"
|
|
10
|
+
SCHEMA = {
|
|
11
|
+
"$schema" => META_SCHEMA_URI,
|
|
12
|
+
"$id" => META_SCHEMA_URI,
|
|
13
|
+
"$dynamicAnchor" => "meta",
|
|
14
|
+
"type" => ["object", "boolean"],
|
|
15
|
+
"properties" => {
|
|
16
|
+
"$id" => {"type" => "string"},
|
|
17
|
+
"$schema" => {"type" => "string"},
|
|
18
|
+
"$ref" => {"type" => "string"},
|
|
19
|
+
"$anchor" => {"type" => "string", "pattern" => "^[A-Za-z_][-A-Za-z0-9._]*$"},
|
|
20
|
+
"$dynamicRef" => {"type" => "string"},
|
|
21
|
+
"$dynamicAnchor" => {"type" => "string", "pattern" => "^[A-Za-z_][-A-Za-z0-9._]*$"},
|
|
22
|
+
"$recursiveRef" => {"type" => "string"},
|
|
23
|
+
"$recursiveAnchor" => {"type" => "string", "pattern" => "^[A-Za-z_][-A-Za-z0-9._]*$"},
|
|
24
|
+
"$vocabulary" => {"type" => "object", "additionalProperties" => {"type" => "boolean"}},
|
|
25
|
+
"$comment" => {"type" => "string"},
|
|
26
|
+
"$defs" => {"type" => "object", "additionalProperties" => {"$dynamicRef" => "#meta"}},
|
|
27
|
+
"definitions" => {"type" => "object", "additionalProperties" => {"$dynamicRef" => "#meta"}},
|
|
28
|
+
"prefixItems" => {
|
|
29
|
+
"type" => "array",
|
|
30
|
+
"minItems" => 1,
|
|
31
|
+
"items" => {"$dynamicRef" => "#meta"}
|
|
32
|
+
},
|
|
33
|
+
"items" => {"$dynamicRef" => "#meta"},
|
|
34
|
+
"contains" => {"$dynamicRef" => "#meta"},
|
|
35
|
+
"additionalProperties" => {"$dynamicRef" => "#meta"},
|
|
36
|
+
"properties" => {"type" => "object", "additionalProperties" => {"$dynamicRef" => "#meta"}},
|
|
37
|
+
"patternProperties" => {"type" => "object", "additionalProperties" => {"$dynamicRef" => "#meta"}},
|
|
38
|
+
"dependentSchemas" => {"type" => "object", "additionalProperties" => {"$dynamicRef" => "#meta"}},
|
|
39
|
+
"dependencies" => {
|
|
40
|
+
"type" => "object",
|
|
41
|
+
"additionalProperties" => {
|
|
42
|
+
"anyOf" => [
|
|
43
|
+
{"$dynamicRef" => "#meta"},
|
|
44
|
+
{"type" => "array", "items" => {"type" => "string"}, "uniqueItems" => true}
|
|
45
|
+
]
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
"propertyNames" => {"$dynamicRef" => "#meta"},
|
|
49
|
+
"if" => {"$dynamicRef" => "#meta"},
|
|
50
|
+
"then" => {"$dynamicRef" => "#meta"},
|
|
51
|
+
"else" => {"$dynamicRef" => "#meta"},
|
|
52
|
+
"allOf" => {"type" => "array", "minItems" => 1, "items" => {"$dynamicRef" => "#meta"}},
|
|
53
|
+
"anyOf" => {"type" => "array", "minItems" => 1, "items" => {"$dynamicRef" => "#meta"}},
|
|
54
|
+
"oneOf" => {"type" => "array", "minItems" => 1, "items" => {"$dynamicRef" => "#meta"}},
|
|
55
|
+
"not" => {"$dynamicRef" => "#meta"},
|
|
56
|
+
"type" => {
|
|
57
|
+
"anyOf" => [
|
|
58
|
+
{"enum" => ["null", "boolean", "object", "array", "number", "integer", "string"]},
|
|
59
|
+
{
|
|
60
|
+
"type" => "array",
|
|
61
|
+
"items" => {"enum" => ["null", "boolean", "object", "array", "number", "integer", "string"]},
|
|
62
|
+
"minItems" => 1,
|
|
63
|
+
"uniqueItems" => true
|
|
64
|
+
}
|
|
65
|
+
]
|
|
66
|
+
},
|
|
67
|
+
"enum" => {"type" => "array"},
|
|
68
|
+
"multipleOf" => {"type" => "number", "exclusiveMinimum" => 0},
|
|
69
|
+
"maximum" => {"type" => "number"},
|
|
70
|
+
"exclusiveMaximum" => {"type" => "number"},
|
|
71
|
+
"minimum" => {"type" => "number"},
|
|
72
|
+
"exclusiveMinimum" => {"type" => "number"},
|
|
73
|
+
"minLength" => {"type" => "integer", "minimum" => 0},
|
|
74
|
+
"maxLength" => {"type" => "integer", "minimum" => 0},
|
|
75
|
+
"pattern" => {"type" => "string"},
|
|
76
|
+
"minItems" => {"type" => "integer", "minimum" => 0},
|
|
77
|
+
"maxItems" => {"type" => "integer", "minimum" => 0},
|
|
78
|
+
"uniqueItems" => {"type" => "boolean"},
|
|
79
|
+
"minContains" => {"type" => "integer", "minimum" => 0},
|
|
80
|
+
"maxContains" => {"type" => "integer", "minimum" => 0},
|
|
81
|
+
"minProperties" => {"type" => "integer", "minimum" => 0},
|
|
82
|
+
"maxProperties" => {"type" => "integer", "minimum" => 0},
|
|
83
|
+
"required" => {
|
|
84
|
+
"type" => "array",
|
|
85
|
+
"items" => {"type" => "string"},
|
|
86
|
+
"uniqueItems" => true
|
|
87
|
+
},
|
|
88
|
+
"dependentRequired" => {
|
|
89
|
+
"type" => "object",
|
|
90
|
+
"additionalProperties" => {
|
|
91
|
+
"type" => "array",
|
|
92
|
+
"items" => {"type" => "string"},
|
|
93
|
+
"uniqueItems" => true
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
"title" => {"type" => "string"},
|
|
97
|
+
"description" => {"type" => "string"},
|
|
98
|
+
"deprecated" => {"type" => "boolean"},
|
|
99
|
+
"readOnly" => {"type" => "boolean"},
|
|
100
|
+
"writeOnly" => {"type" => "boolean"},
|
|
101
|
+
"examples" => {"type" => "array"},
|
|
102
|
+
"format" => {"type" => "string"},
|
|
103
|
+
"contentEncoding" => {"type" => "string"},
|
|
104
|
+
"contentMediaType" => {"type" => "string"},
|
|
105
|
+
"contentSchema" => {"$dynamicRef" => "#meta"}
|
|
106
|
+
}
|
|
107
|
+
}.freeze
|
|
108
|
+
|
|
109
|
+
MetaSchemas.register(META_SCHEMA_URI, SCHEMA)
|
|
110
|
+
|
|
111
|
+
COMPONENT_KEYWORDS = {
|
|
112
|
+
"core" => %w[
|
|
113
|
+
$id $schema $ref $anchor $dynamicRef $dynamicAnchor $vocabulary $comment $defs
|
|
114
|
+
],
|
|
115
|
+
"applicator" => %w[
|
|
116
|
+
prefixItems items contains additionalProperties properties patternProperties
|
|
117
|
+
dependentSchemas propertyNames if then else allOf anyOf oneOf not
|
|
118
|
+
],
|
|
119
|
+
"unevaluated" => %w[unevaluatedItems unevaluatedProperties],
|
|
120
|
+
"validation" => %w[
|
|
121
|
+
type const enum multipleOf maximum exclusiveMaximum minimum exclusiveMinimum
|
|
122
|
+
maxLength minLength pattern maxItems minItems uniqueItems maxContains minContains
|
|
123
|
+
maxProperties minProperties required dependentRequired
|
|
124
|
+
],
|
|
125
|
+
"meta-data" => %w[title description default deprecated readOnly writeOnly examples],
|
|
126
|
+
"format-annotation" => %w[format],
|
|
127
|
+
"format-assertion" => %w[format],
|
|
128
|
+
"content" => %w[contentEncoding contentMediaType contentSchema]
|
|
129
|
+
}.freeze
|
|
130
|
+
|
|
131
|
+
COMPONENT_KEYWORDS.each do |name, keywords|
|
|
132
|
+
uri = "https://json-schema.org/draft/2020-12/meta/#{name}"
|
|
133
|
+
component = {
|
|
134
|
+
"$schema" => META_SCHEMA_URI,
|
|
135
|
+
"$id" => uri,
|
|
136
|
+
"$dynamicAnchor" => "meta",
|
|
137
|
+
"type" => ["object", "boolean"],
|
|
138
|
+
"properties" => SCHEMA.fetch("properties").slice(*keywords)
|
|
139
|
+
}.freeze
|
|
140
|
+
MetaSchemas.register(uri, component)
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
private_constant :META_SCHEMA_URI, :SCHEMA, :COMPONENT_KEYWORDS
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
private_constant :Internal
|
|
149
|
+
end
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../meta_schemas"
|
|
4
|
+
|
|
5
|
+
module Schemurai
|
|
6
|
+
module Internal
|
|
7
|
+
module MetaSchemas
|
|
8
|
+
module Draft7
|
|
9
|
+
META_SCHEMA_URI = "http://json-schema.org/draft-07/schema"
|
|
10
|
+
SCHEMA = {
|
|
11
|
+
"$schema" => "#{META_SCHEMA_URI}#",
|
|
12
|
+
"$id" => "#{META_SCHEMA_URI}#",
|
|
13
|
+
"definitions" => {
|
|
14
|
+
"schemaArray" => {"type" => "array", "minItems" => 1, "items" => {"$ref" => "#"}},
|
|
15
|
+
"nonNegativeInteger" => {"type" => "integer", "minimum" => 0},
|
|
16
|
+
"nonNegativeIntegerDefault0" => {
|
|
17
|
+
"allOf" => [
|
|
18
|
+
{"$ref" => "#/definitions/nonNegativeInteger"},
|
|
19
|
+
{"default" => 0}
|
|
20
|
+
]
|
|
21
|
+
},
|
|
22
|
+
"simpleTypes" => {"enum" => %w[array boolean integer null number object string]},
|
|
23
|
+
"stringArray" => {
|
|
24
|
+
"type" => "array",
|
|
25
|
+
"items" => {"type" => "string"},
|
|
26
|
+
"uniqueItems" => true,
|
|
27
|
+
"default" => []
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"type" => ["object", "boolean"],
|
|
31
|
+
"properties" => {
|
|
32
|
+
"$id" => {"type" => "string", "format" => "uri-reference"},
|
|
33
|
+
"$schema" => {"type" => "string", "format" => "uri"},
|
|
34
|
+
"$ref" => {"type" => "string", "format" => "uri-reference"},
|
|
35
|
+
"$comment" => {"type" => "string"},
|
|
36
|
+
"title" => {"type" => "string"},
|
|
37
|
+
"description" => {"type" => "string"},
|
|
38
|
+
"default" => true,
|
|
39
|
+
"readOnly" => {"type" => "boolean", "default" => false},
|
|
40
|
+
"writeOnly" => {"type" => "boolean", "default" => false},
|
|
41
|
+
"examples" => {"type" => "array", "items" => true},
|
|
42
|
+
"multipleOf" => {"type" => "number", "exclusiveMinimum" => 0},
|
|
43
|
+
"maximum" => {"type" => "number"},
|
|
44
|
+
"exclusiveMaximum" => {"type" => "number"},
|
|
45
|
+
"minimum" => {"type" => "number"},
|
|
46
|
+
"exclusiveMinimum" => {"type" => "number"},
|
|
47
|
+
"maxLength" => {"$ref" => "#/definitions/nonNegativeInteger"},
|
|
48
|
+
"minLength" => {"$ref" => "#/definitions/nonNegativeIntegerDefault0"},
|
|
49
|
+
"pattern" => {"type" => "string", "format" => "regex"},
|
|
50
|
+
"additionalItems" => {"$ref" => "#"},
|
|
51
|
+
"items" => {
|
|
52
|
+
"anyOf" => [{"$ref" => "#"}, {"$ref" => "#/definitions/schemaArray"}],
|
|
53
|
+
"default" => true
|
|
54
|
+
},
|
|
55
|
+
"maxItems" => {"$ref" => "#/definitions/nonNegativeInteger"},
|
|
56
|
+
"minItems" => {"$ref" => "#/definitions/nonNegativeIntegerDefault0"},
|
|
57
|
+
"uniqueItems" => {"type" => "boolean", "default" => false},
|
|
58
|
+
"contains" => {"$ref" => "#"},
|
|
59
|
+
"maxProperties" => {"$ref" => "#/definitions/nonNegativeInteger"},
|
|
60
|
+
"minProperties" => {"$ref" => "#/definitions/nonNegativeIntegerDefault0"},
|
|
61
|
+
"required" => {"$ref" => "#/definitions/stringArray"},
|
|
62
|
+
"additionalProperties" => {"$ref" => "#"},
|
|
63
|
+
"definitions" => {
|
|
64
|
+
"type" => "object",
|
|
65
|
+
"additionalProperties" => {"$ref" => "#"},
|
|
66
|
+
"default" => {}
|
|
67
|
+
},
|
|
68
|
+
"properties" => {
|
|
69
|
+
"type" => "object",
|
|
70
|
+
"additionalProperties" => {"$ref" => "#"},
|
|
71
|
+
"default" => {}
|
|
72
|
+
},
|
|
73
|
+
"patternProperties" => {
|
|
74
|
+
"type" => "object",
|
|
75
|
+
"additionalProperties" => {"$ref" => "#"},
|
|
76
|
+
"propertyNames" => {"format" => "regex"},
|
|
77
|
+
"default" => {}
|
|
78
|
+
},
|
|
79
|
+
"dependencies" => {
|
|
80
|
+
"type" => "object",
|
|
81
|
+
"additionalProperties" => {
|
|
82
|
+
"anyOf" => [{"$ref" => "#"}, {"$ref" => "#/definitions/stringArray"}]
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
"propertyNames" => {"$ref" => "#"},
|
|
86
|
+
"const" => true,
|
|
87
|
+
"enum" => {"type" => "array", "items" => true, "minItems" => 1, "uniqueItems" => true},
|
|
88
|
+
"type" => {
|
|
89
|
+
"anyOf" => [
|
|
90
|
+
{"$ref" => "#/definitions/simpleTypes"},
|
|
91
|
+
{
|
|
92
|
+
"type" => "array",
|
|
93
|
+
"items" => {"$ref" => "#/definitions/simpleTypes"},
|
|
94
|
+
"minItems" => 1,
|
|
95
|
+
"uniqueItems" => true
|
|
96
|
+
}
|
|
97
|
+
]
|
|
98
|
+
},
|
|
99
|
+
"format" => {"type" => "string"},
|
|
100
|
+
"contentMediaType" => {"type" => "string"},
|
|
101
|
+
"contentEncoding" => {"type" => "string"},
|
|
102
|
+
"if" => {"$ref" => "#"},
|
|
103
|
+
"then" => {"$ref" => "#"},
|
|
104
|
+
"else" => {"$ref" => "#"},
|
|
105
|
+
"allOf" => {"$ref" => "#/definitions/schemaArray"},
|
|
106
|
+
"anyOf" => {"$ref" => "#/definitions/schemaArray"},
|
|
107
|
+
"oneOf" => {"$ref" => "#/definitions/schemaArray"},
|
|
108
|
+
"not" => {"$ref" => "#"}
|
|
109
|
+
},
|
|
110
|
+
"default" => true
|
|
111
|
+
}.freeze
|
|
112
|
+
|
|
113
|
+
MetaSchemas.register(META_SCHEMA_URI, SCHEMA)
|
|
114
|
+
|
|
115
|
+
private_constant :META_SCHEMA_URI, :SCHEMA
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
private_constant :Internal
|
|
121
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Schemurai
|
|
4
|
+
module Internal
|
|
5
|
+
module MetaSchemas
|
|
6
|
+
class << self
|
|
7
|
+
def register(uri, schema)
|
|
8
|
+
registry[normalize_uri(uri)] = schema
|
|
9
|
+
schema
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def resolve(uri)
|
|
13
|
+
registry[normalize_uri(uri)]
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
private def registry
|
|
17
|
+
@registry ||= {}
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
private def normalize_uri(uri)
|
|
21
|
+
uri.to_s.delete_suffix("#")
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
private_constant :Internal
|
|
28
|
+
end
|
|
Binary file
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Schemurai
|
|
4
|
+
module Native
|
|
5
|
+
# Render native diagnostic output using the messages shared by every backend.
|
|
6
|
+
# The instance remains an original Ruby object; this layer never traverses it.
|
|
7
|
+
module Diagnostics
|
|
8
|
+
TYPE_NAMES = {Protocol::OP_TYPE_NULL => "null", Protocol::OP_TYPE_BOOLEAN => "boolean", Protocol::OP_TYPE_OBJECT => "object",
|
|
9
|
+
Protocol::OP_TYPE_ARRAY => "array", Protocol::OP_TYPE_NUMBER => "number", Protocol::OP_TYPE_INTEGER => "integer",
|
|
10
|
+
Protocol::OP_TYPE_STRING => "string", Protocol::OP_TYPED_NUMBER => "number", Protocol::OP_TYPED_INTEGER => "integer",
|
|
11
|
+
Protocol::OP_TYPED_STRING => "string", Protocol::OP_TYPED_ARRAY => "array", Protocol::OP_TYPED_OBJECT => "object"}.freeze
|
|
12
|
+
ATTRIBUTES = {"maximum" => :maximum, "minimum" => :minimum, "exclusiveMaximum" => :exclusive_maximum, "exclusiveMinimum" => :exclusive_minimum,
|
|
13
|
+
"maxLength" => :max_length, "minLength" => :min_length, "maxItems" => :max_items, "minItems" => :min_items,
|
|
14
|
+
"maxProperties" => :max_properties, "minProperties" => :min_properties}.freeze
|
|
15
|
+
private_constant :TYPE_NAMES, :ATTRIBUTES
|
|
16
|
+
|
|
17
|
+
module_function def error(row)
|
|
18
|
+
keyword, instance_path, schema_path, opcode, operand, instance, detail, rendered_message = row
|
|
19
|
+
ValidationError.new(keyword: keyword, instance_path: instance_path, schema_path: schema_path,
|
|
20
|
+
message: rendered_message || message(keyword, opcode, operand, instance, detail))
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
module_function def message(keyword, opcode, operand, instance, detail) # rubocop:disable Metrics/MethodLength
|
|
24
|
+
messages = Internal::ErrorMessage
|
|
25
|
+
case keyword
|
|
26
|
+
when "falseSchema" then messages.false_schema
|
|
27
|
+
when "type" then messages.type((opcode == Protocol::OP_TYPES) ? operand.names : TYPE_NAMES.fetch(opcode), instance)
|
|
28
|
+
when "const" then messages.const
|
|
29
|
+
when "enum" then messages.enum
|
|
30
|
+
when "maximum", "minimum", "exclusiveMaximum", "exclusiveMinimum"
|
|
31
|
+
messages.numeric_limit(keyword, operand.public_send(ATTRIBUTES.fetch(keyword)))
|
|
32
|
+
when "multipleOf" then messages.multiple_of(operand.multiple_of)
|
|
33
|
+
when "maxLength", "minLength", "maxItems", "minItems", "maxProperties", "minProperties"
|
|
34
|
+
messages.size(keyword, operand.public_send(ATTRIBUTES.fetch(keyword)), detail)
|
|
35
|
+
when "pattern" then (detail == 1) ? messages.invalid_pattern(operand.pattern) : messages.pattern(operand.pattern)
|
|
36
|
+
when "format" then messages.format(operand.format.name)
|
|
37
|
+
when "contentEncoding" then messages.content_encoding
|
|
38
|
+
when "contentMediaType" then messages.content_media_type
|
|
39
|
+
when "uniqueItems" then messages.unique_items
|
|
40
|
+
when "required" then messages.required(instance)
|
|
41
|
+
when "dependencies", "dependentRequired" then messages.dependent_required(operand, instance)
|
|
42
|
+
when "contains" then messages.contains(detail, operand.min_contains, operand.max_contains)
|
|
43
|
+
when "anyOf" then messages.any_of
|
|
44
|
+
when "oneOf" then messages.one_of(detail)
|
|
45
|
+
when "not" then messages.not
|
|
46
|
+
when "$ref", "$recursiveRef", "$dynamicRef" then operand
|
|
47
|
+
else raise "unknown native diagnostic #{keyword.inspect}"
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
private_class_method :message
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../decimal"
|
|
4
|
+
require_relative "../number_checks"
|
|
5
|
+
require_relative "../string_checks"
|
|
6
|
+
require_relative "../value_equality"
|
|
7
|
+
require_relative "../container_checks"
|
|
8
|
+
require_relative "../type_checks"
|
|
9
|
+
require_relative "../vm/compiler"
|
|
10
|
+
require_relative "../evaluation_pool"
|
|
11
|
+
require_relative "../limit_budget"
|
|
12
|
+
require_relative "../ecma_regexp"
|
|
13
|
+
require_relative "../json_pointer"
|
|
14
|
+
require "schemurai_native"
|
|
15
|
+
require_relative "diagnostics"
|
|
16
|
+
require_relative "null_numeric"
|
|
17
|
+
|
|
18
|
+
module Schemurai
|
|
19
|
+
module Native
|
|
20
|
+
class Evaluator
|
|
21
|
+
def backend = :native
|
|
22
|
+
|
|
23
|
+
def initialize(graph, compiler, root, content: false, format: false, compiled: nil)
|
|
24
|
+
@graph = graph
|
|
25
|
+
@compiler = compiler
|
|
26
|
+
@root = root
|
|
27
|
+
@content = content
|
|
28
|
+
@format = format
|
|
29
|
+
@graph_size = @graph.nodes.length
|
|
30
|
+
@compiled = compiled || Program.new(root, compiler, format, content)
|
|
31
|
+
@number_state = Internal::NumberChecks::State.new
|
|
32
|
+
@regexps = {}
|
|
33
|
+
@scope_state = []
|
|
34
|
+
@report_state = [nil, Internal::EvaluationPool.new]
|
|
35
|
+
@reference_state = []
|
|
36
|
+
@active_state = {}.compare_by_identity
|
|
37
|
+
@program = @compiled.runner(root)
|
|
38
|
+
@program.share_scalar_state(@number_state, @regexps, @scope_state, @reference_state, @active_state, @report_state)
|
|
39
|
+
@unresolved = @compiled.unresolved_references?
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def valid?(instance, max_errors: nil, timeout: nil)
|
|
43
|
+
refresh_unresolved
|
|
44
|
+
if !max_errors.nil? || !timeout.nil?
|
|
45
|
+
budget = Internal::LimitBudget.new(max_errors: max_errors, timeout: timeout)
|
|
46
|
+
result = @program.valid_with_budget(instance, budget)
|
|
47
|
+
budget.check_deadline!
|
|
48
|
+
return result
|
|
49
|
+
end
|
|
50
|
+
@program.valid?(instance)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def validate(instance, max_errors: nil, timeout: nil)
|
|
54
|
+
refresh_unresolved
|
|
55
|
+
if !max_errors.nil? || !timeout.nil?
|
|
56
|
+
budget = Internal::LimitBudget.new(max_errors: max_errors, timeout: timeout)
|
|
57
|
+
rows = @program.diagnostics_with_budget(instance, budget)
|
|
58
|
+
|
|
59
|
+
errors = (rows == false) ? nil : rows.map do |row|
|
|
60
|
+
budget.reserve_error
|
|
61
|
+
Diagnostics.error(row)
|
|
62
|
+
end
|
|
63
|
+
budget.check_deadline!
|
|
64
|
+
return Result.new(errors)
|
|
65
|
+
end
|
|
66
|
+
rows = @program.diagnostics(instance)
|
|
67
|
+
|
|
68
|
+
return Result.new(nil) if rows == false
|
|
69
|
+
|
|
70
|
+
Result.new(rows.empty? ? rows : rows.map { |row| Diagnostics.error(row) })
|
|
71
|
+
end
|
|
72
|
+
private def refresh_unresolved
|
|
73
|
+
while @unresolved && @graph_size != @graph.nodes.length
|
|
74
|
+
graph_size = @graph.nodes.length
|
|
75
|
+
compiled = Program.new(@root, @compiler, @format, @content)
|
|
76
|
+
@program = compiled.runner(@root)
|
|
77
|
+
@program.share_scalar_state(@number_state, @regexps, @scope_state, @reference_state, @active_state, @report_state)
|
|
78
|
+
@compiled = compiled
|
|
79
|
+
@unresolved = @compiled.unresolved_references?
|
|
80
|
+
@graph_size = graph_size
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
private_constant :Native
|
|
87
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Schemurai
|
|
4
|
+
module Native
|
|
5
|
+
# Native traversal selects one reached assertion and its comparison mode.
|
|
6
|
+
# Ruby dispatch preserves the exception and method visibility for nil.
|
|
7
|
+
module NullNumeric
|
|
8
|
+
module_function def valid?(value, bit, decimal)
|
|
9
|
+
actual = if decimal && !value.is_a?(Integer) && !value.is_a?(Rational)
|
|
10
|
+
Internal::Decimal.parse(value)
|
|
11
|
+
else
|
|
12
|
+
value
|
|
13
|
+
end
|
|
14
|
+
case bit
|
|
15
|
+
when Protocol::MAXIMUM, Protocol::MINIMUM, Protocol::EXCLUSIVE_MAXIMUM, Protocol::EXCLUSIVE_MINIMUM
|
|
16
|
+
Internal::NumberChecks.bound?(actual, bit, nil)
|
|
17
|
+
when Protocol::MULTIPLE_OF then nil.positive? && actual.remainder(nil).zero?
|
|
18
|
+
else raise "unknown null numeric assertion"
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|