corvus_json_schema 0.1.0
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/Cargo.lock +390 -0
- data/Cargo.toml +8 -0
- data/LICENSE +201 -0
- data/README.md +111 -0
- data/VERSIONHISTORY.md +7 -0
- data/ext/corvus_json_schema/Cargo.toml +18 -0
- data/ext/corvus_json_schema/extconf.rb +6 -0
- data/ext/corvus_json_schema/rustfmt.toml +2 -0
- data/ext/corvus_json_schema/src/lib.rs +643 -0
- data/ext/corvus_json_schema/vendor/corvus-json-schema/Cargo.toml +35 -0
- data/ext/corvus_json_schema/vendor/corvus-json-schema/LICENSE +201 -0
- data/ext/corvus_json_schema/vendor/corvus-json-schema/README.md +139 -0
- data/ext/corvus_json_schema/vendor/corvus-json-schema/src/compiler.rs +1118 -0
- data/ext/corvus_json_schema/vendor/corvus-json-schema/src/dialect.rs +108 -0
- data/ext/corvus_json_schema/vendor/corvus-json-schema/src/document.rs +905 -0
- data/ext/corvus_json_schema/vendor/corvus-json-schema/src/eval/plan/fused.rs +1187 -0
- data/ext/corvus_json_schema/vendor/corvus-json-schema/src/eval/plan.rs +1728 -0
- data/ext/corvus_json_schema/vendor/corvus-json-schema/src/eval.rs +1451 -0
- data/ext/corvus_json_schema/vendor/corvus-json-schema/src/formats.rs +1021 -0
- data/ext/corvus_json_schema/vendor/corvus-json-schema/src/instance.rs +228 -0
- data/ext/corvus_json_schema/vendor/corvus-json-schema/src/lib.rs +189 -0
- data/ext/corvus_json_schema/vendor/corvus-json-schema/src/loader.rs +403 -0
- data/ext/corvus_json_schema/vendor/corvus-json-schema/src/metaschemas.rs +29 -0
- data/ext/corvus_json_schema/vendor/corvus-json-schema/src/node.rs +417 -0
- data/ext/corvus_json_schema/vendor/corvus-json-schema/src/numbers.rs +244 -0
- data/ext/corvus_json_schema/vendor/corvus-json-schema/src/options.rs +108 -0
- data/ext/corvus_json_schema/vendor/corvus-json-schema/src/pattern.rs +1591 -0
- data/ext/corvus_json_schema/vendor/corvus-json-schema/src/results.rs +316 -0
- data/ext/corvus_json_schema/vendor/corvus-json-schema/src/uri.rs +274 -0
- data/lib/corvus_json_schema/version.rb +5 -0
- data/lib/corvus_json_schema.rb +65 -0
- metadata +94 -0
data/README.md
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# corvus_json_schema
|
|
2
|
+
|
|
3
|
+
A JSON Schema evaluator for Ruby (draft 4, 6, 7, 2019-09 and 2020-12), a native extension over the
|
|
4
|
+
[corvus-json-schema](https://crates.io/crates/corvus-json-schema) Rust crate, the Rust port of the Corvus.Text.Json V5
|
|
5
|
+
standalone evaluator.
|
|
6
|
+
|
|
7
|
+
- **Conformant**: passes the JSON-Schema-Test-Suite (required, optional and `optional/format`, every draft) except
|
|
8
|
+
`draft4/optional/zeroTerminatedFloats.json`, which the other Corvus evaluators also exclude (a JSON parser reads
|
|
9
|
+
`1.0` as an integer).
|
|
10
|
+
- **Fast**: values are read in place from Ruby's own objects (nothing is converted or copied), and JSON text is
|
|
11
|
+
validated without creating Ruby objects for it.
|
|
12
|
+
- **Precompiled**: native gems for Linux (x86_64 and aarch64, glibc and musl), macOS (x86_64 and arm64) and Windows
|
|
13
|
+
(x64), for Ruby 3.3, 3.4 and 4.0. On other platforms the source gem builds the extension, which needs a Rust
|
|
14
|
+
toolchain (1.85 or later) and libclang.
|
|
15
|
+
|
|
16
|
+
## Install
|
|
17
|
+
|
|
18
|
+
```sh
|
|
19
|
+
gem install corvus_json_schema
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Usage
|
|
23
|
+
|
|
24
|
+
```ruby
|
|
25
|
+
require "corvus_json_schema"
|
|
26
|
+
|
|
27
|
+
validator = CorvusJsonSchema.compile({
|
|
28
|
+
"type" => "object", "required" => ["id"], "properties" => { "id" => { "type" => "integer" } }
|
|
29
|
+
})
|
|
30
|
+
validator.valid?({ "id" => 3 }) # => true: a Hash, read in place
|
|
31
|
+
validator.valid?({ id: "3" }) # => false: Symbol keys are read as their names
|
|
32
|
+
validator.valid_json?('{"id": 3}') # => true: JSON text, parsed in Rust
|
|
33
|
+
|
|
34
|
+
collector = CorvusJsonSchema::Collector.new(:detailed)
|
|
35
|
+
validator.evaluate({ "id" => "3" }, collector) # => false
|
|
36
|
+
collector.results
|
|
37
|
+
# => [..., { is_match: false, message: "The value was expected to be of type 'integer'",
|
|
38
|
+
# evaluation_location: "/properties/id/type", schema_location: "/properties/id/type",
|
|
39
|
+
# instance_location: "/id" }, ...]
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
`CorvusJsonSchema.compile(schema, **options)` takes the schema as a Hash, an Array, `true` or `false`, or JSON text.
|
|
43
|
+
Its options:
|
|
44
|
+
|
|
45
|
+
| Option | Default | Meaning |
|
|
46
|
+
| --- | --- | --- |
|
|
47
|
+
| `default_dialect` | `:draft202012` | The dialect of a schema without `$schema`: `:draft4`, `:draft6`, `:draft7`, `:draft201909` or `:draft202012`. |
|
|
48
|
+
| `assert_format` | `nil` | Whether `format` is asserted; `nil` follows the schema's vocabularies. |
|
|
49
|
+
| `assert_format_in_legacy_drafts` | `false` | Assert `format` in drafts 4 to 7 when `assert_format` is `nil`. |
|
|
50
|
+
| `assert_content` | `true` | Assert `contentEncoding` and `contentMediaType` in drafts 4 to 7. |
|
|
51
|
+
| `formats` | `nil` | A Hash of format name to a callable that takes the string and returns whether it is valid. |
|
|
52
|
+
| `resolver` | `nil` | A callable that takes an absolute URI and returns the document (a Hash or JSON text), or `nil` when it has none. |
|
|
53
|
+
| `base_uri` | `nil` | The schema's base URI, when it has no `$id`. |
|
|
54
|
+
| `entry_point` | `nil` | A reference to the subschema to validate against, such as `"#/$defs/item"`. |
|
|
55
|
+
| `max_depth` | `128` | The deepest the evaluator recurses in place before it raises `DepthError`. |
|
|
56
|
+
|
|
57
|
+
A `Validator` is immutable and can be shared between threads.
|
|
58
|
+
|
|
59
|
+
- `valid?(value)` and `valid_json?(text)` return whether the instance is valid, evaluating only as far as the answer
|
|
60
|
+
needs.
|
|
61
|
+
- `evaluate(value, collector)` evaluates every keyword and replaces the collector's results with this evaluation's.
|
|
62
|
+
`Collector.new(level)` takes `:basic` (the failures, without messages), `:detailed` (the failures, with messages)
|
|
63
|
+
or `:verbose` (every result, and annotations); at every level the root's own result is the last row. `results`
|
|
64
|
+
returns its rows and `annotations` the annotations of a verbose evaluation, grouped by instance location, keyword and
|
|
65
|
+
schema location.
|
|
66
|
+
|
|
67
|
+
Errors are subclasses of `CorvusJsonSchema::Error`: `CompilationError` (an invalid schema, or a reference that cannot
|
|
68
|
+
be resolved), `DepthError` and `InvalidJsonError` (for `valid_json?`). An error raised by a format or resolver callable
|
|
69
|
+
propagates.
|
|
70
|
+
|
|
71
|
+
## Values
|
|
72
|
+
|
|
73
|
+
A value is read as its JSON kind: a `Hash` (String or Symbol keys) is an object, an `Array` an array, a `String` (UTF-8
|
|
74
|
+
or US-ASCII) or `Symbol` a string, an `Integer` or `Float` a number, and `true`, `false` and `nil` themselves. An
|
|
75
|
+
Integer beyond 64 bits is compared as the nearest double, as by a JSON parser without arbitrary precision.
|
|
76
|
+
|
|
77
|
+
Values are read only as the schema examines them, so a value the schema never looks at is not checked: with
|
|
78
|
+
`{"type" => "object"}`, `{ "a" => Object.new }` is valid. A value the schema does examine that is none of the kinds
|
|
79
|
+
above raises `TypeError` (`ArgumentError` for a NaN or infinite Float, `EncodingError` for a String that is not valid
|
|
80
|
+
UTF-8).
|
|
81
|
+
|
|
82
|
+
## How it works
|
|
83
|
+
|
|
84
|
+
The crate compiles the schema once into its node graph and fail-fast plans (see
|
|
85
|
+
[src-rs/corvus-json-schema](../../src-rs/corvus-json-schema/README.md)). Its evaluator is generic over an `Instance`
|
|
86
|
+
trait (a value shown as one of the six JSON kinds, with arrays and objects read in place), which this extension
|
|
87
|
+
implements over Ruby values: arrays are read by index, strings as the bytes Ruby holds, and a Hash's pairs are gathered
|
|
88
|
+
(with `rb_hash_foreach`) into a buffer reused across evaluations when the evaluator first reads that object.
|
|
89
|
+
Evaluation allocates no Ruby objects, so Ruby's garbage collector cannot run, and so cannot move a value, while it
|
|
90
|
+
reads them; when custom formats (Ruby code, which can allocate) are in use, the instance is first converted to the
|
|
91
|
+
crate's own form instead.
|
|
92
|
+
|
|
93
|
+
`valid_json?` parses into the crate's `JsonDocument`, whose buffers are reused for each thread: in the steady state a
|
|
94
|
+
validation of JSON text allocates nothing.
|
|
95
|
+
|
|
96
|
+
## Building from source
|
|
97
|
+
|
|
98
|
+
In this repository, with Ruby 3.3 or later, a Rust toolchain and libclang:
|
|
99
|
+
|
|
100
|
+
```sh
|
|
101
|
+
bundle install
|
|
102
|
+
bundle exec rake compile test
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
The Rakefile copies the crate from `src-rs/corvus-json-schema` into `ext/corvus_json_schema/vendor` whenever it loads,
|
|
106
|
+
so the source gem carries the crate's sources and builds on its own. The tests run the JSON-Schema-Test-Suite from the
|
|
107
|
+
repository's submodule (or `JSON_SCHEMA_TEST_SUITE`).
|
|
108
|
+
|
|
109
|
+
## License
|
|
110
|
+
|
|
111
|
+
Apache-2.0
|
data/VERSIONHISTORY.md
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Version History
|
|
2
|
+
|
|
3
|
+
The version history of the `corvus_json_schema` Ruby gem. It is versioned independently of the Corvus NuGet packages and of the [corvus-json-schema](../../src-rs/corvus-json-schema/VERSIONHISTORY.md) Rust crate it is built on.
|
|
4
|
+
|
|
5
|
+
## V0.1.0
|
|
6
|
+
|
|
7
|
+
The first release: a native extension over the corvus-json-schema Rust crate (0.1.3), for drafts 4, 6, 7, 2019-09 and 2020-12. It reads Ruby values in place, validates JSON text without creating Ruby objects for it, and collects results (Basic, Detailed and Verbose) and annotations. It passes the whole JSON-Schema-Test-Suite, read in place, as JSON text and through a collector.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
[package]
|
|
2
|
+
name = "corvus_json_schema"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
edition = "2024"
|
|
5
|
+
rust-version = "1.85"
|
|
6
|
+
description = "The native extension of the corvus_json_schema gem: the corvus-json-schema crate, reading Ruby values in place."
|
|
7
|
+
license = "Apache-2.0"
|
|
8
|
+
publish = false
|
|
9
|
+
|
|
10
|
+
[lib]
|
|
11
|
+
crate-type = ["cdylib"]
|
|
12
|
+
|
|
13
|
+
[dependencies]
|
|
14
|
+
# The crate, copied in by `rake vendor` (from src-rs/corvus-json-schema) so that the source gem builds on its own.
|
|
15
|
+
corvus = { package = "corvus-json-schema", path = "vendor/corvus-json-schema", version = "0.1.3" }
|
|
16
|
+
magnus = { version = "0.9.1", features = ["rb-sys"] }
|
|
17
|
+
rb-sys = "0.9.130"
|
|
18
|
+
serde_json = { version = "1.0.151", features = ["preserve_order", "float_roundtrip"] }
|