rusty_json_schema 0.1.0 → 0.2.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/Cargo.toml +1 -0
- data/README.md +25 -4
- data/lib/ext/json_schema.dll +0 -0
- data/lib/ext/json_schema.dll.exp +0 -0
- data/lib/ext/json_schema.dll.lib +0 -0
- data/lib/ext/json_schema.pdb +0 -0
- data/lib/ext/libjson_schema.dylib +0 -0
- data/lib/ext/libjson_schema.so +0 -0
- data/lib/rusty_json_schema.rb +25 -38
- data/lib/rusty_json_schema/binding.rb +28 -0
- data/lib/rusty_json_schema/nodes_array.rb +26 -0
- data/lib/rusty_json_schema/validator.rb +30 -0
- data/lib/rusty_json_schema/version.rb +1 -1
- data/rusty_json_schema.gemspec +1 -0
- data/src/lib.rs +164 -14
- metadata +19 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dd6b9fde168fe809a7285e76360ae1a87c55c3e0603d4e4901b76f1b4c101674
|
4
|
+
data.tar.gz: '08b4831a5dff32132d473d17470fc992c4b6a453472366eca4f7b511b84fea2a'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7b45b35d8d14862cf402215993c2075885ad014a2c80a41394bf9959495a4ecb5993d17bb31d479260f83746325e6c1b3527dfaa630af8967a884f4413ef9f5f
|
7
|
+
data.tar.gz: a70e61c95d6f55d66da0848fa4edc0a78dad1fa08da140eca8c2f0af8d0365f51eff7f8ee7dfdb855ffe6de1488b0c1499b0bddf3a357a9e34e89a0c4b414404
|
data/Cargo.toml
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
# RustyJSONSchema
|
2
2
|
|
3
|
-
|
3
|
+
[](https://badge.fury.io/rb/rusty_json_schema)
|
4
|
+
|
5
|
+
FFI wrapper around [`jsonschema`](https://github.com/Stranger6667/jsonschema-rs) Rust library. Props go to original project.
|
4
6
|
|
5
7
|
Currently during heavy development.
|
6
8
|
|
@@ -14,11 +16,15 @@ gem "rusty_json_schema"
|
|
14
16
|
|
15
17
|
And then execute:
|
16
18
|
|
17
|
-
|
19
|
+
```
|
20
|
+
$ bundle install
|
21
|
+
```
|
18
22
|
|
19
23
|
Or install it yourself as:
|
20
24
|
|
21
|
-
|
25
|
+
```
|
26
|
+
$ gem install rusty_json_schema
|
27
|
+
```
|
22
28
|
|
23
29
|
## Usage
|
24
30
|
|
@@ -32,13 +38,28 @@ Validate events like
|
|
32
38
|
|
33
39
|
```ruby
|
34
40
|
validator.valid?(event_json)
|
41
|
+
# => true/false
|
42
|
+
```
|
43
|
+
|
44
|
+
To get validation errors
|
45
|
+
|
46
|
+
```ruby
|
47
|
+
validator.validate(event_json)
|
48
|
+
# => ["invalid...", ...]
|
35
49
|
```
|
36
50
|
|
37
51
|
## Development
|
38
52
|
|
39
53
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
40
54
|
|
41
|
-
To install this gem onto your local machine, run `bundle exec rake install`.
|
55
|
+
To install this gem onto your local machine, run `bundle exec rake install`.
|
56
|
+
|
57
|
+
To release a new version:
|
58
|
+
|
59
|
+
- update version number in `version.rb` & `CHANGELOG.md`
|
60
|
+
- create GitHub release with tag being new version prefixed with `v`, i.e. for `VERSION="0.1.0"` it would be `v0.1.0`
|
61
|
+
- pull `*.gem` artifact from release build
|
62
|
+
- `gem push *.gem` in order to publish it in [rubygems.org](https://rubygems.org).
|
42
63
|
|
43
64
|
## Contributing
|
44
65
|
|
data/lib/ext/json_schema.dll
CHANGED
Binary file
|
data/lib/ext/json_schema.dll.exp
CHANGED
Binary file
|
data/lib/ext/json_schema.dll.lib
CHANGED
Binary file
|
data/lib/ext/json_schema.pdb
CHANGED
Binary file
|
Binary file
|
data/lib/ext/libjson_schema.so
CHANGED
Binary file
|
data/lib/rusty_json_schema.rb
CHANGED
@@ -1,62 +1,49 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "ffi"
|
4
|
+
require "json"
|
4
5
|
|
5
|
-
|
6
|
+
require "rusty_json_schema/version"
|
7
|
+
require "rusty_json_schema/nodes_array"
|
8
|
+
require "rusty_json_schema/validator"
|
9
|
+
require "rusty_json_schema/binding"
|
6
10
|
|
7
11
|
# JSON Schema validation
|
8
12
|
#
|
9
13
|
# ## Example
|
10
14
|
#
|
11
|
-
# validator = RustyJSONSchema.build(schema)
|
12
|
-
#
|
15
|
+
# validator = RustyJSONSchema.build(schema)
|
16
|
+
#
|
17
|
+
# validator.valid?(event)
|
13
18
|
# # => true/false
|
14
19
|
#
|
20
|
+
# validator.validate(event)
|
21
|
+
# # => [] / ["...error messages", ...]
|
22
|
+
#
|
15
23
|
module RustyJSONSchema
|
16
24
|
|
17
|
-
def self.build(schema)
|
18
|
-
RustyJSONSchema::Validator::Binding.new(schema)
|
19
|
-
end
|
20
|
-
|
21
25
|
class Error < StandardError; end
|
22
26
|
|
23
|
-
|
24
|
-
# with Ruby GC. This way we can intialize validator
|
25
|
-
# in Rust, and hold a reference in Ruby.
|
26
|
-
#
|
27
|
-
class Validator < FFI::AutoPointer
|
27
|
+
class << self
|
28
28
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
Binding.free(pointer)
|
29
|
+
attr_writer :processor
|
30
|
+
|
31
|
+
def processor
|
32
|
+
@processor ||= JSON
|
34
33
|
end
|
35
34
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
35
|
+
def dump(data)
|
36
|
+
case data
|
37
|
+
when String then data
|
38
|
+
else processor.dump(data)
|
39
|
+
end
|
40
40
|
end
|
41
41
|
|
42
|
-
#
|
42
|
+
# Helper method that returns new instance of pointer
|
43
|
+
# to Validator struct.
|
43
44
|
#
|
44
|
-
|
45
|
-
|
46
|
-
extend FFI::Library
|
47
|
-
|
48
|
-
lib_name =
|
49
|
-
case ::FFI::Platform::LIBSUFFIX
|
50
|
-
when "so", "dylib" then "libjson_schema"
|
51
|
-
when "dll" then "json_schema"
|
52
|
-
end
|
53
|
-
|
54
|
-
ffi_lib File.expand_path("ext/#{lib_name}.#{::FFI::Platform::LIBSUFFIX}", __dir__)
|
55
|
-
|
56
|
-
attach_function :new, :validator_new, [:string], Validator
|
57
|
-
attach_function :free, :validator_free, [Validator], :void
|
58
|
-
attach_function :is_valid, :validator_is_valid, [Validator, :string], :bool
|
59
|
-
|
45
|
+
def build(schema)
|
46
|
+
RustyJSONSchema::Binding.new(dump(schema))
|
60
47
|
end
|
61
48
|
|
62
49
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RustyJSONSchema
|
4
|
+
|
5
|
+
# Integration point between Rust jsonschema wrapper
|
6
|
+
# and RustyJSONSchema.
|
7
|
+
#
|
8
|
+
module Binding
|
9
|
+
|
10
|
+
extend FFI::Library
|
11
|
+
|
12
|
+
lib_name =
|
13
|
+
case ::FFI::Platform::LIBSUFFIX
|
14
|
+
when "so", "dylib" then "libjson_schema"
|
15
|
+
when "dll" then "json_schema"
|
16
|
+
end
|
17
|
+
|
18
|
+
ffi_lib File.expand_path("../ext/#{lib_name}.#{::FFI::Platform::LIBSUFFIX}", __dir__)
|
19
|
+
|
20
|
+
attach_function :new, :validator_new, [:string], Validator
|
21
|
+
attach_function :free, :validator_free, [Validator], :void
|
22
|
+
attach_function :free_array, :array_free, [NodesArray], :void
|
23
|
+
attach_function :is_valid, :validator_is_valid, [Validator, :string], :bool
|
24
|
+
attach_function :validate, :validator_validate, [Validator, :string], NodesArray.by_ref
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RustyJSONSchema
|
4
|
+
|
5
|
+
# Struct representing list of errors returned from
|
6
|
+
# our wrapper library. Use ManagedStruct in order to
|
7
|
+
# properly release nested strings which would otherwise
|
8
|
+
# leak and pollute the memory.
|
9
|
+
#
|
10
|
+
class NodesArray < FFI::ManagedStruct
|
11
|
+
|
12
|
+
layout :data, :pointer,
|
13
|
+
:len, :uint,
|
14
|
+
:cap, :uint
|
15
|
+
|
16
|
+
def to_a
|
17
|
+
self[:data].get_array_of_string(0, self[:len]).compact
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.release(ptr)
|
21
|
+
Binding.free_array(ptr)
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RustyJSONSchema
|
4
|
+
|
5
|
+
# Handles release of the pointer automatically
|
6
|
+
# with Ruby GC. This way we can intialize validator
|
7
|
+
# in Rust, and hold a reference in Ruby.
|
8
|
+
#
|
9
|
+
class Validator < FFI::AutoPointer
|
10
|
+
|
11
|
+
# Custom GC flow for our validator, freeing
|
12
|
+
# the object within Rust
|
13
|
+
#
|
14
|
+
def self.release(pointer)
|
15
|
+
Binding.free(pointer)
|
16
|
+
end
|
17
|
+
|
18
|
+
# Simple validation without actual error messages
|
19
|
+
#
|
20
|
+
def valid?(event)
|
21
|
+
Binding.is_valid(self, RustyJSONSchema.dump(event))
|
22
|
+
end
|
23
|
+
|
24
|
+
def validate(event)
|
25
|
+
Binding.validate(self, RustyJSONSchema.dump(event)).to_a
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
data/rusty_json_schema.gemspec
CHANGED
data/src/lib.rs
CHANGED
@@ -1,8 +1,10 @@
|
|
1
|
+
extern crate libc;
|
2
|
+
|
1
3
|
use jsonschema::JSONSchema;
|
2
4
|
use serde_json::Value;
|
3
5
|
|
4
|
-
use std::ffi::CStr;
|
5
|
-
use std::os::raw::c_char;
|
6
|
+
use std::ffi::{CStr, CString};
|
7
|
+
use std::os::raw::{c_char, c_uint};
|
6
8
|
|
7
9
|
/*
|
8
10
|
* Our wrapper struct for schema and schema value,
|
@@ -22,7 +24,8 @@ impl Validator {
|
|
22
24
|
*/
|
23
25
|
fn new(schema: Value) -> Validator {
|
24
26
|
let boxed_schema: &'static Value = Box::leak(Box::new(schema));
|
25
|
-
let boxed_compile: &'static JSONSchema<'static> =
|
27
|
+
let boxed_compile: &'static JSONSchema<'static> =
|
28
|
+
Box::leak(Box::new(JSONSchema::compile(boxed_schema).unwrap()));
|
26
29
|
|
27
30
|
Validator {
|
28
31
|
schema: boxed_compile,
|
@@ -33,6 +36,18 @@ impl Validator {
|
|
33
36
|
fn is_valid(&self, event: &Value) -> bool {
|
34
37
|
self.schema.is_valid(event)
|
35
38
|
}
|
39
|
+
|
40
|
+
fn validate(&self, event: &Value) -> Vec<String> {
|
41
|
+
let mut errors: Vec<String> = vec![];
|
42
|
+
|
43
|
+
if let Err(validation_errors) = self.schema.validate(event) {
|
44
|
+
for error in validation_errors {
|
45
|
+
errors.push(error.to_string());
|
46
|
+
}
|
47
|
+
}
|
48
|
+
|
49
|
+
errors
|
50
|
+
}
|
36
51
|
}
|
37
52
|
|
38
53
|
impl Drop for Validator {
|
@@ -48,6 +63,36 @@ impl Drop for Validator {
|
|
48
63
|
}
|
49
64
|
}
|
50
65
|
|
66
|
+
#[repr(C)]
|
67
|
+
pub struct Array {
|
68
|
+
data: *mut *mut c_char,
|
69
|
+
len: c_uint,
|
70
|
+
cap: c_uint,
|
71
|
+
}
|
72
|
+
|
73
|
+
impl Array {
|
74
|
+
fn from_vec(from: Vec<String>) -> Self {
|
75
|
+
let mut converted: Vec<*mut c_char> = from
|
76
|
+
.into_iter()
|
77
|
+
.map(|s| CString::new(s).unwrap().into_raw())
|
78
|
+
.collect();
|
79
|
+
|
80
|
+
converted.shrink_to_fit();
|
81
|
+
|
82
|
+
let len = converted.len();
|
83
|
+
let cap = converted.capacity();
|
84
|
+
let result = Array {
|
85
|
+
data: converted.as_mut_ptr(),
|
86
|
+
len: len as c_uint,
|
87
|
+
cap: cap as c_uint,
|
88
|
+
};
|
89
|
+
|
90
|
+
std::mem::forget(converted);
|
91
|
+
|
92
|
+
result
|
93
|
+
}
|
94
|
+
}
|
95
|
+
|
51
96
|
fn to_string(ptr: *const c_char) -> &'static CStr {
|
52
97
|
unsafe {
|
53
98
|
assert!(!ptr.is_null());
|
@@ -57,7 +102,7 @@ fn to_string(ptr: *const c_char) -> &'static CStr {
|
|
57
102
|
|
58
103
|
#[no_mangle]
|
59
104
|
pub extern "C" fn validator_new(c_schema: *const c_char) -> *mut Validator {
|
60
|
-
let raw_schema
|
105
|
+
let raw_schema = to_string(c_schema);
|
61
106
|
let schema = serde_json::from_slice(raw_schema.to_bytes()).unwrap();
|
62
107
|
let validator = Validator::new(schema);
|
63
108
|
|
@@ -65,6 +110,7 @@ pub extern "C" fn validator_new(c_schema: *const c_char) -> *mut Validator {
|
|
65
110
|
}
|
66
111
|
|
67
112
|
#[no_mangle]
|
113
|
+
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
68
114
|
pub extern "C" fn validator_free(ptr: *mut Validator) {
|
69
115
|
if ptr.is_null() {
|
70
116
|
return;
|
@@ -76,6 +122,7 @@ pub extern "C" fn validator_free(ptr: *mut Validator) {
|
|
76
122
|
}
|
77
123
|
|
78
124
|
#[no_mangle]
|
125
|
+
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
79
126
|
pub extern "C" fn validator_is_valid(ptr: *const Validator, event: *const c_char) -> bool {
|
80
127
|
let validator = unsafe {
|
81
128
|
assert!(!ptr.is_null());
|
@@ -88,31 +135,134 @@ pub extern "C" fn validator_is_valid(ptr: *const Validator, event: *const c_char
|
|
88
135
|
validator.is_valid(&event)
|
89
136
|
}
|
90
137
|
|
138
|
+
#[no_mangle]
|
139
|
+
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
140
|
+
pub extern "C" fn validator_validate(ptr: *const Validator, event: *const c_char) -> *mut Array {
|
141
|
+
let validator = unsafe {
|
142
|
+
assert!(!ptr.is_null());
|
143
|
+
&*ptr
|
144
|
+
};
|
145
|
+
|
146
|
+
let raw_event = to_string(event);
|
147
|
+
let event: Value = serde_json::from_slice(raw_event.to_bytes()).unwrap();
|
148
|
+
let errors = validator.validate(&event);
|
149
|
+
let result = Array::from_vec(errors);
|
150
|
+
let boxed = Box::new(result);
|
151
|
+
|
152
|
+
Box::into_raw(boxed)
|
153
|
+
}
|
154
|
+
|
155
|
+
#[no_mangle]
|
156
|
+
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
157
|
+
pub extern "C" fn array_free(ptr: *mut Array) {
|
158
|
+
if ptr.is_null() {
|
159
|
+
return;
|
160
|
+
}
|
161
|
+
|
162
|
+
unsafe {
|
163
|
+
let array = Box::from_raw(ptr);
|
164
|
+
let data = Vec::from_raw_parts(array.data, array.len as usize, array.cap as usize);
|
165
|
+
|
166
|
+
for string in data {
|
167
|
+
let _ = CString::from_raw(string);
|
168
|
+
}
|
169
|
+
}
|
170
|
+
}
|
171
|
+
|
91
172
|
#[cfg(test)]
|
92
173
|
mod tests {
|
93
174
|
// Note this useful idiom: importing names from outer (for mod tests) scope.
|
94
175
|
use super::*;
|
95
176
|
use std::ffi::CString;
|
96
|
-
use std::{thread, time};
|
97
177
|
|
98
178
|
/*
|
99
179
|
* Simple sanity check if everything works together
|
100
180
|
*/
|
101
181
|
#[test]
|
102
182
|
fn test_valid_event() {
|
103
|
-
let
|
104
|
-
|
105
|
-
|
183
|
+
let validator = validator_new(helper_c_schema().as_ptr());
|
184
|
+
|
185
|
+
assert!(validator_is_valid(validator, helper_c_valid().as_ptr()));
|
186
|
+
|
187
|
+
assert!(!validator_is_valid(validator, helper_c_invalid().as_ptr()));
|
188
|
+
|
189
|
+
validator_free(validator);
|
190
|
+
}
|
191
|
+
|
192
|
+
#[test]
|
193
|
+
fn test_validate_event_when_valid() {
|
194
|
+
let validator = validator_new(helper_c_schema().as_ptr());
|
195
|
+
let raw_result = validator_validate(validator, helper_c_valid().as_ptr());
|
196
|
+
let result = unsafe { helper_validate_result_as_vec(raw_result) };
|
197
|
+
|
198
|
+
let expectation: Vec<String> = vec![];
|
199
|
+
|
200
|
+
assert_eq!(result, expectation);
|
106
201
|
|
107
|
-
|
108
|
-
|
109
|
-
|
202
|
+
validator_free(validator);
|
203
|
+
}
|
204
|
+
|
205
|
+
#[test]
|
206
|
+
fn test_validate_event_when_invalid() {
|
207
|
+
let validator = validator_new(helper_c_schema().as_ptr());
|
208
|
+
let raw_result = validator_validate(validator, helper_c_invalid().as_ptr());
|
209
|
+
let result = unsafe { helper_validate_result_as_vec(raw_result) };
|
110
210
|
|
111
|
-
let
|
211
|
+
let expectation: Vec<String> = vec![
|
212
|
+
String::from("\'\"rusty\"\' is not of type \'number\'"),
|
213
|
+
String::from("\'1\' is not of type \'string\'"),
|
214
|
+
String::from("\'baz\' is a required property"),
|
215
|
+
];
|
112
216
|
|
113
|
-
|
114
|
-
assert!(!validator_is_valid(validator, c_invalid_event_ptr));
|
217
|
+
assert_eq!(result, expectation);
|
115
218
|
|
116
219
|
validator_free(validator);
|
117
220
|
}
|
221
|
+
|
222
|
+
/*
|
223
|
+
* Test helpers
|
224
|
+
*/
|
225
|
+
fn helper_c_schema() -> CString {
|
226
|
+
CString::new(
|
227
|
+
r#"{
|
228
|
+
"properties":{
|
229
|
+
"foo": {"type": "string"},
|
230
|
+
"bar": {"type": "number"},
|
231
|
+
"baz": {}
|
232
|
+
},
|
233
|
+
"required": ["baz"]
|
234
|
+
}"#,
|
235
|
+
)
|
236
|
+
.unwrap()
|
237
|
+
}
|
238
|
+
|
239
|
+
fn helper_c_valid() -> CString {
|
240
|
+
CString::new(
|
241
|
+
r#"{
|
242
|
+
"foo": "rusty",
|
243
|
+
"bar": 1,
|
244
|
+
"baz": "rusty"
|
245
|
+
}"#,
|
246
|
+
)
|
247
|
+
.unwrap()
|
248
|
+
}
|
249
|
+
|
250
|
+
fn helper_c_invalid() -> CString {
|
251
|
+
CString::new(
|
252
|
+
r#"{
|
253
|
+
"foo": 1,
|
254
|
+
"bar": "rusty"
|
255
|
+
}"#,
|
256
|
+
)
|
257
|
+
.unwrap()
|
258
|
+
}
|
259
|
+
|
260
|
+
unsafe fn helper_validate_result_as_vec(result: *mut Array) -> Vec<String> {
|
261
|
+
let raw = Box::from_raw(result);
|
262
|
+
|
263
|
+
Vec::from_raw_parts(raw.data, raw.len as usize, raw.cap as usize)
|
264
|
+
.into_iter()
|
265
|
+
.map(|x| CString::from_raw(x).into_string().unwrap())
|
266
|
+
.collect()
|
267
|
+
}
|
118
268
|
}
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rusty_json_schema
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Leszek Zalewski
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-12-
|
11
|
+
date: 2020-12-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ffi
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '1.14'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: json
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.0'
|
27
41
|
description: |2
|
28
42
|
FFI wrapper around https://github.com/Stranger6667/jsonschema-rs Rust library.
|
29
43
|
|
@@ -45,6 +59,9 @@ files:
|
|
45
59
|
- lib/ext/libjson_schema.dylib
|
46
60
|
- lib/ext/libjson_schema.so
|
47
61
|
- lib/rusty_json_schema.rb
|
62
|
+
- lib/rusty_json_schema/binding.rb
|
63
|
+
- lib/rusty_json_schema/nodes_array.rb
|
64
|
+
- lib/rusty_json_schema/validator.rb
|
48
65
|
- lib/rusty_json_schema/version.rb
|
49
66
|
- rusty_json_schema.gemspec
|
50
67
|
- src/lib.rs
|