schemurai 2.2.3 → 2.3.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 +4 -4
- data/README.md +14 -3
- data/ext/schemurai_native/Cargo.lock +99 -0
- data/ext/schemurai_native/Cargo.toml +21 -0
- data/ext/schemurai_native/build.rs +35 -0
- data/ext/schemurai_native/extconf.rb +63 -0
- data/ext/schemurai_native/glue.c +639 -0
- data/ext/schemurai_native/protocol.def +63 -0
- data/ext/schemurai_native/protocol.h +10 -0
- data/ext/schemurai_native/src/content.rs +574 -0
- data/ext/schemurai_native/src/diagnostics.rs +965 -0
- data/ext/schemurai_native/src/format.rs +357 -0
- data/ext/schemurai_native/src/lib.rs +2376 -0
- data/ext/schemurai_native/src/number.rs +1055 -0
- data/ext/schemurai_native/src/pattern.rs +288 -0
- data/ext/schemurai_native/src/scope.rs +210 -0
- data/ext/schemurai_native/src/tracking.rs +532 -0
- data/lib/schemurai/backend.rb +2 -1
- data/lib/schemurai/native/diagnostics.rb +52 -0
- data/lib/schemurai/native/evaluator.rb +32 -0
- data/lib/schemurai/version.rb +1 -1
- data/lib/schemurai.rb +8 -7
- data/sig/schemurai.rbs +1 -1
- metadata +22 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 181bce310181bba515fd0b38021092300deda955ce8ef5cefb6b9e077a51995b
|
|
4
|
+
data.tar.gz: 506c85192a973967b9787637fb96c24d564ebf83bba7e02124f8fccf3de9de55
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b6b8663cd944bd3c439892a0ebbbaea1fbce229eabe208094e89f1999cc102b60a6b04a2626caafa2dc480a18e76c4c76aca75433f2509d84ab75f1766e14e0c
|
|
7
|
+
data.tar.gz: 4a80f08e3f35eb1edfab8d106d2967c4fdc686741b5e731f4bc7dc5c5946095a6e69272cc8257ad1d762746b78df73e932a9470a0815969c25ff54274e62631b
|
data/README.md
CHANGED
|
@@ -5,13 +5,18 @@
|
|
|
5
5
|
[](https://github.com/oakcask/schemurai/actions/workflows/lint--rubocop.yaml)
|
|
6
6
|
[](https://github.com/oakcask/schemurai/actions/workflows/lint--rbs.yaml)
|
|
7
7
|
|
|
8
|
-
A
|
|
9
|
-
Draft 2019-09, and Draft 2020-12
|
|
10
|
-
JSON-Schema-Test-Suite, as well as
|
|
8
|
+
A JSON Schema validator for Ruby with reusable compiled schemas and detailed
|
|
9
|
+
validation errors. It supports Draft 7, Draft 2019-09, and Draft 2020-12 and
|
|
10
|
+
covers the required cases in the official JSON-Schema-Test-Suite, as well as
|
|
11
|
+
the applicable optional tests for numeric
|
|
11
12
|
precision, ECMA-262 regular expressions, content validation, anchors, and dynamic
|
|
12
13
|
references. The dialect is selected from the schema's `$schema` URI; schemas that
|
|
13
14
|
omit `$schema` use Draft 7 for compatibility.
|
|
14
15
|
|
|
16
|
+
Choose the default Ruby evaluator, the Ruby VM backend, or the optional
|
|
17
|
+
experimental Rust native backend. See [backend selection](#backend-selection)
|
|
18
|
+
for setup and requirements.
|
|
19
|
+
|
|
15
20
|
Schemurai ships RBS declarations for its public API in `sig/schemurai.rbs`.
|
|
16
21
|
|
|
17
22
|
```ruby
|
|
@@ -218,6 +223,12 @@ validator is retained.
|
|
|
218
223
|
`Schemurai.backend`, `SchemaRegistry#backend`, and `Validator#backend` expose
|
|
219
224
|
the actual backend. Pass `backend: :ruby` to force the Ruby oracle or
|
|
220
225
|
`backend: :vm` to ahead-of-time compile schemas for the validator virtual machine.
|
|
226
|
+
Pass `backend: :native` to use the experimental Rust VM extension. Building the
|
|
227
|
+
native extension requires a C toolchain, Ruby development headers, and Rust
|
|
228
|
+
1.93 or newer. If cargo is absent, gem installation skips the optional native
|
|
229
|
+
extension and Ruby/VM remain available; explicitly selecting `:native` then
|
|
230
|
+
raises `LoadError`. Native execution borrows Ruby values directly; its current coverage and
|
|
231
|
+
remaining VM delegation are documented below.
|
|
221
232
|
Schema graph construction remains shared Ruby infrastructure. Environment-based selection
|
|
222
233
|
is documented in [`docs/backend-selection.md`](docs/backend-selection.md).
|
|
223
234
|
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# This file is automatically @generated by Cargo.
|
|
2
|
+
# It is not intended for manual editing.
|
|
3
|
+
version = 4
|
|
4
|
+
|
|
5
|
+
[[package]]
|
|
6
|
+
name = "aho-corasick"
|
|
7
|
+
version = "1.1.5"
|
|
8
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
9
|
+
checksum = "c982642fa9e8606056828ee9a8505737230110bb1099153c79efe865c59d12ba"
|
|
10
|
+
dependencies = [
|
|
11
|
+
"memchr",
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
[[package]]
|
|
15
|
+
name = "base64-simd"
|
|
16
|
+
version = "0.8.0"
|
|
17
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
18
|
+
checksum = "339abbe78e73178762e23bea9dfd08e697eb3f3301cd4be981c0f78ba5859195"
|
|
19
|
+
dependencies = [
|
|
20
|
+
"outref",
|
|
21
|
+
"vsimd",
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
[[package]]
|
|
25
|
+
name = "base64-turbo"
|
|
26
|
+
version = "0.5.0"
|
|
27
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
28
|
+
checksum = "865a269d8d8fc97f16122eae7a74e7e9dffa2df68d5f067cb1f494e9984528db"
|
|
29
|
+
dependencies = [
|
|
30
|
+
"cpufeatures",
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
[[package]]
|
|
34
|
+
name = "cpufeatures"
|
|
35
|
+
version = "0.3.1"
|
|
36
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
37
|
+
checksum = "5ca28b0ae3115b884660db4118d803791fd6756b6e88f39c0f3f7859060d7566"
|
|
38
|
+
dependencies = [
|
|
39
|
+
"libc",
|
|
40
|
+
]
|
|
41
|
+
|
|
42
|
+
[[package]]
|
|
43
|
+
name = "libc"
|
|
44
|
+
version = "0.2.190"
|
|
45
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
46
|
+
checksum = "ce5d3ddc6d3fa000eb1536d85e147bfe31aacaba692ed6a876f95cb7c855be78"
|
|
47
|
+
|
|
48
|
+
[[package]]
|
|
49
|
+
name = "memchr"
|
|
50
|
+
version = "2.8.3"
|
|
51
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
52
|
+
checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98"
|
|
53
|
+
|
|
54
|
+
[[package]]
|
|
55
|
+
name = "outref"
|
|
56
|
+
version = "0.5.2"
|
|
57
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
58
|
+
checksum = "1a80800c0488c3a21695ea981a54918fbb37abf04f4d0720c453632255e2ff0e"
|
|
59
|
+
|
|
60
|
+
[[package]]
|
|
61
|
+
name = "regex-automata"
|
|
62
|
+
version = "0.4.18"
|
|
63
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
64
|
+
checksum = "ad8553b9b26413251cbf30e620595c7a41b3887f03da04579c0e6b0d6a06b4b2"
|
|
65
|
+
dependencies = [
|
|
66
|
+
"aho-corasick",
|
|
67
|
+
"memchr",
|
|
68
|
+
"regex-syntax",
|
|
69
|
+
]
|
|
70
|
+
|
|
71
|
+
[[package]]
|
|
72
|
+
name = "regex-syntax"
|
|
73
|
+
version = "0.8.11"
|
|
74
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
75
|
+
checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4"
|
|
76
|
+
|
|
77
|
+
[[package]]
|
|
78
|
+
name = "ryu"
|
|
79
|
+
version = "1.0.23"
|
|
80
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
81
|
+
checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f"
|
|
82
|
+
|
|
83
|
+
[[package]]
|
|
84
|
+
name = "schemurai-native"
|
|
85
|
+
version = "2.3.0"
|
|
86
|
+
dependencies = [
|
|
87
|
+
"base64-simd",
|
|
88
|
+
"base64-turbo",
|
|
89
|
+
"memchr",
|
|
90
|
+
"regex-automata",
|
|
91
|
+
"regex-syntax",
|
|
92
|
+
"ryu",
|
|
93
|
+
]
|
|
94
|
+
|
|
95
|
+
[[package]]
|
|
96
|
+
name = "vsimd"
|
|
97
|
+
version = "0.8.0"
|
|
98
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
99
|
+
checksum = "5c3082ca00d5a5ef149bb8b555a72ae84c9c59f7250f013ac822ac2e49b19c64"
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
[package]
|
|
2
|
+
name = "schemurai-native"
|
|
3
|
+
version = "2.3.0"
|
|
4
|
+
edition = "2024"
|
|
5
|
+
rust-version = "1.93"
|
|
6
|
+
publish = false
|
|
7
|
+
|
|
8
|
+
[dependencies]
|
|
9
|
+
base64-simd = "0.8.0"
|
|
10
|
+
base64-turbo = "0.5.0"
|
|
11
|
+
memchr = "2.8.3"
|
|
12
|
+
regex-automata = "0.4.18"
|
|
13
|
+
regex-syntax = "0.8.11"
|
|
14
|
+
ryu = "1.0.23"
|
|
15
|
+
|
|
16
|
+
[lib]
|
|
17
|
+
crate-type = ["staticlib"]
|
|
18
|
+
|
|
19
|
+
[profile.release]
|
|
20
|
+
lto = true
|
|
21
|
+
codegen-units = 1
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
use std::{env, fs, path::PathBuf};
|
|
2
|
+
|
|
3
|
+
fn main() {
|
|
4
|
+
println!("cargo:rerun-if-changed=protocol.def");
|
|
5
|
+
let definitions = fs::read_to_string("protocol.def").expect("read native protocol");
|
|
6
|
+
let mut output = String::new();
|
|
7
|
+
for line in definitions.lines() {
|
|
8
|
+
let (fields, opcode) = if let Some(fields) = line.strip_prefix("SN_OPCODE(") {
|
|
9
|
+
(fields, true)
|
|
10
|
+
} else if let Some(fields) = line.strip_prefix("SN_CONSTANT(") {
|
|
11
|
+
(fields, false)
|
|
12
|
+
} else {
|
|
13
|
+
continue;
|
|
14
|
+
};
|
|
15
|
+
let fields: Vec<_> = fields
|
|
16
|
+
.strip_suffix(')')
|
|
17
|
+
.expect("protocol closing parenthesis")
|
|
18
|
+
.split(',')
|
|
19
|
+
.map(str::trim)
|
|
20
|
+
.collect();
|
|
21
|
+
assert_eq!(fields.len(), if opcode { 3 } else { 2 });
|
|
22
|
+
let name = fields[0];
|
|
23
|
+
assert!(
|
|
24
|
+
name.bytes()
|
|
25
|
+
.all(|c| c.is_ascii_uppercase() || c.is_ascii_digit() || c == b'_')
|
|
26
|
+
);
|
|
27
|
+
let value: i32 = fields[if opcode { 2 } else { 1 }]
|
|
28
|
+
.parse()
|
|
29
|
+
.expect("protocol integer value");
|
|
30
|
+
let prefix = if opcode { "OP_" } else { "" };
|
|
31
|
+
output.push_str(&format!("pub const {prefix}{name}: i32 = {value};\n"));
|
|
32
|
+
}
|
|
33
|
+
let directory = PathBuf::from(env::var_os("OUT_DIR").expect("Cargo output directory"));
|
|
34
|
+
fs::write(directory.join("protocol.rs"), output).expect("write native protocol constants");
|
|
35
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "mkmf"
|
|
4
|
+
|
|
5
|
+
unless find_executable("cargo")
|
|
6
|
+
warn "cargo was not found; skipping the optional native backend (Ruby and VM remain available)"
|
|
7
|
+
File.write("Makefile", dummy_makefile(".").join)
|
|
8
|
+
exit
|
|
9
|
+
end
|
|
10
|
+
unless enable_config("portable-hash-walk", false)
|
|
11
|
+
if have_func("rb_hash_stlike_foreach", ["ruby.h", "ruby/st.h"])
|
|
12
|
+
# CRuby 3.4/4.0 identity Hashes always use ST storage. Check the private
|
|
13
|
+
# storage flag against a fresh interpreter before enabling the read hint.
|
|
14
|
+
ar_proof = !CROSS_COMPILING && try_run(<<~C)
|
|
15
|
+
#include <ruby.h>
|
|
16
|
+
#include <ruby/version.h>
|
|
17
|
+
#if (RUBY_API_VERSION_MAJOR == 3 && RUBY_API_VERSION_MINOR == 4) || \
|
|
18
|
+
(RUBY_API_VERSION_MAJOR == 4 && RUBY_API_VERSION_MINOR == 0)
|
|
19
|
+
int main(int argc, char **argv) {
|
|
20
|
+
ruby_sysinit(&argc, &argv);
|
|
21
|
+
RUBY_INIT_STACK;
|
|
22
|
+
ruby_init();
|
|
23
|
+
int status = 0;
|
|
24
|
+
ID identity = rb_intern_const("compare_by_identity");
|
|
25
|
+
for (int n = 0; n <= 8; n++) {
|
|
26
|
+
VALUE h = rb_hash_new();
|
|
27
|
+
VALUE id = rb_funcall(rb_hash_new(), identity, 0);
|
|
28
|
+
for (int i = 0; i < n; i++) {
|
|
29
|
+
rb_hash_aset(h, INT2FIX(i), INT2FIX(i));
|
|
30
|
+
rb_hash_aset(id, INT2FIX(i), INT2FIX(i));
|
|
31
|
+
}
|
|
32
|
+
VALUE hashes[] = {h, rb_obj_freeze(rb_hash_dup(h)),
|
|
33
|
+
rb_funcall(rb_hash_dup(h), identity, 0), id};
|
|
34
|
+
for (int i = 0; i < 4; i++) {
|
|
35
|
+
int st = RB_FL_TEST_RAW(hashes[i], RUBY_FL_USER3) != 0;
|
|
36
|
+
if (st != (i >= 2)) status = 1;
|
|
37
|
+
}
|
|
38
|
+
RB_GC_GUARD(h);
|
|
39
|
+
RB_GC_GUARD(id);
|
|
40
|
+
}
|
|
41
|
+
return ruby_cleanup(status);
|
|
42
|
+
}
|
|
43
|
+
#else
|
|
44
|
+
int main(void) { return 1; }
|
|
45
|
+
#endif
|
|
46
|
+
C
|
|
47
|
+
$defs << "-DSCHEMURAI_AR_HASH_PROOF" if ar_proof # rubocop:disable Style/GlobalVars -- mkmf build configuration.
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
$LOCAL_LIBS << " $(srcdir)/target/release/libschemurai_native.a" # rubocop:disable Style/GlobalVars -- mkmf build configuration.
|
|
51
|
+
$LOCAL_LIBS << " -lpthread -ldl -lm" unless /mswin|mingw/ =~ RUBY_PLATFORM # rubocop:disable Style/GlobalVars -- mkmf build configuration.
|
|
52
|
+
create_makefile("schemurai_native")
|
|
53
|
+
File.open("Makefile", "a") do |file|
|
|
54
|
+
file.puts <<~MAKE
|
|
55
|
+
|
|
56
|
+
$(TARGET_SO): $(srcdir)/target/release/libschemurai_native.a
|
|
57
|
+
|
|
58
|
+
glue.o: $(srcdir)/protocol.h $(srcdir)/protocol.def
|
|
59
|
+
|
|
60
|
+
$(srcdir)/target/release/libschemurai_native.a: $(srcdir)/Cargo.toml $(srcdir)/Cargo.lock $(srcdir)/build.rs $(srcdir)/protocol.def $(wildcard $(srcdir)/src/*.rs)
|
|
61
|
+
\tcargo build --manifest-path $(srcdir)/Cargo.toml --release --locked
|
|
62
|
+
MAKE
|
|
63
|
+
end
|