rusty_json_schema 0.3.0-x64-mingw32
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.toml +14 -0
- data/README.md +74 -0
- data/ext/Rakefile +36 -0
- data/ext/json_schema.so.default +0 -0
- data/lib/rusty_json_schema.rb +51 -0
- data/lib/rusty_json_schema/binding.rb +22 -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 +7 -0
- data/lib/tasks/thermite_dir_patch.rb +13 -0
- data/rusty_json_schema.gemspec +46 -0
- data/src/lib.rs +268 -0
- metadata +106 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: ef776b75f005158065c0c6a7d41f89fee9abcb565f71d4268e15ddfd9f8afe67
|
4
|
+
data.tar.gz: 529d0e8fd559c0d103c6a451e074d41415cf06807a26990d5a545a29706acccf
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: fddf71983ca50ca850292390aea7d8cb9f39dfc0ffd9a4b10d122a8d31c2d407b2c1a53a9e6588511c5eecbfb690dd0443099b75cbef37bb13582bbc5e61ff8a
|
7
|
+
data.tar.gz: d51b14c7c352ceb284be2bb852f27d88d793f6678683ea827c2088e18e3ca356117c99d2d0e63ecce8915bc2391a1bf5349ecb48b494712b6dc40af17a7c8586
|
data/Cargo.toml
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
[package]
|
2
|
+
name = "json_schema"
|
3
|
+
version = "0.3.0"
|
4
|
+
authors = ["Leszek Zalewski <leszekzalewski@fastmail.fm>"]
|
5
|
+
edition = "2018"
|
6
|
+
|
7
|
+
[lib]
|
8
|
+
name = "json_schema"
|
9
|
+
crate-type = ["cdylib"]
|
10
|
+
|
11
|
+
[dependencies]
|
12
|
+
libc = "0.2.81"
|
13
|
+
jsonschema = "0.4.3"
|
14
|
+
serde_json = "1.0"
|
data/README.md
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
# RustyJSONSchema
|
2
|
+
|
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.
|
6
|
+
|
7
|
+
Currently during heavy development.
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
Add this line to your application's Gemfile:
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
gem "rusty_json_schema"
|
15
|
+
```
|
16
|
+
|
17
|
+
And then execute:
|
18
|
+
|
19
|
+
```
|
20
|
+
$ bundle install
|
21
|
+
```
|
22
|
+
|
23
|
+
Or install it yourself as:
|
24
|
+
|
25
|
+
```
|
26
|
+
$ gem install rusty_json_schema
|
27
|
+
```
|
28
|
+
|
29
|
+
## Usage
|
30
|
+
|
31
|
+
Initialize schema validator
|
32
|
+
|
33
|
+
```ruby
|
34
|
+
validator = RustyJSONSchema.build(json_schema)
|
35
|
+
```
|
36
|
+
|
37
|
+
Validate events like
|
38
|
+
|
39
|
+
```ruby
|
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...", ...]
|
49
|
+
```
|
50
|
+
|
51
|
+
## Development
|
52
|
+
|
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.
|
54
|
+
|
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).
|
63
|
+
|
64
|
+
## Contributing
|
65
|
+
|
66
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/driv3r/rusty_json_schema. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/driv3r/rusty_json_schema/blob/master/CODE_OF_CONDUCT.md).
|
67
|
+
|
68
|
+
## License
|
69
|
+
|
70
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
71
|
+
|
72
|
+
## Code of Conduct
|
73
|
+
|
74
|
+
Everyone interacting in the RustyJSONSchema project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/driv3r/rusty_json_schema/blob/master/CODE_OF_CONDUCT.md).
|
data/ext/Rakefile
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "thermite/tasks"
|
4
|
+
require_relative "../lib/tasks/thermite_dir_patch"
|
5
|
+
|
6
|
+
project_dir = File.dirname(File.dirname(__FILE__))
|
7
|
+
thermite = Thermite::Tasks.new(cargo_project_path: project_dir,
|
8
|
+
ruby_project_path: project_dir,
|
9
|
+
optional_rust_extension: true)
|
10
|
+
|
11
|
+
namespace :thermite do
|
12
|
+
desc "Try to build extension if cargo is available or setup default lib"
|
13
|
+
task :build_or_default do
|
14
|
+
if thermite.cargo
|
15
|
+
profile = ENV.fetch("CARGO_PROFILE", "release")
|
16
|
+
thermite.run_cargo_rustc(profile)
|
17
|
+
|
18
|
+
FileUtils.cp(thermite.config.cargo_target_path(profile, thermite.config.cargo_shared_library),
|
19
|
+
thermite.config.ruby_extension_path)
|
20
|
+
else
|
21
|
+
puts "NOTE: Defaults to pre-build binary => your mileage may vary."
|
22
|
+
|
23
|
+
FileUtils.mv("#{thermite.config.ruby_extension_path}.default",
|
24
|
+
thermite.config.ruby_extension_path)
|
25
|
+
|
26
|
+
thermite.inform_user_about_cargo
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
desc "Cleanup cargo artifacts"
|
31
|
+
task :cargo_clean do
|
32
|
+
thermite.run_cargo_if_exists "clean", *thermite.cargo_manifest_path_args
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
task default: %w[thermite:build_or_default thermite:cargo_clean]
|
Binary file
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "ffi"
|
4
|
+
require "json"
|
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"
|
10
|
+
|
11
|
+
# JSON Schema validation
|
12
|
+
#
|
13
|
+
# ## Example
|
14
|
+
#
|
15
|
+
# validator = RustyJSONSchema.build(schema)
|
16
|
+
#
|
17
|
+
# validator.valid?(event)
|
18
|
+
# # => true/false
|
19
|
+
#
|
20
|
+
# validator.validate(event)
|
21
|
+
# # => [] / ["...error messages", ...]
|
22
|
+
#
|
23
|
+
module RustyJSONSchema
|
24
|
+
|
25
|
+
class Error < StandardError; end
|
26
|
+
|
27
|
+
class << self
|
28
|
+
|
29
|
+
attr_writer :processor
|
30
|
+
|
31
|
+
def processor
|
32
|
+
@processor ||= JSON
|
33
|
+
end
|
34
|
+
|
35
|
+
def dump(data)
|
36
|
+
case data
|
37
|
+
when String then data
|
38
|
+
else processor.dump(data)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# Helper method that returns new instance of pointer
|
43
|
+
# to Validator struct.
|
44
|
+
#
|
45
|
+
def build(schema)
|
46
|
+
RustyJSONSchema::Binding.new(dump(schema))
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
@@ -0,0 +1,22 @@
|
|
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
|
+
ffi_lib File.expand_path("../../ext/json_schema.so", __dir__)
|
13
|
+
|
14
|
+
attach_function :new, :validator_new, [:string], Validator
|
15
|
+
attach_function :free, :validator_free, [Validator], :void
|
16
|
+
attach_function :free_array, :array_free, [NodesArray], :void
|
17
|
+
attach_function :is_valid, :validator_is_valid, [Validator, :string], :bool
|
18
|
+
attach_function :validate, :validator_validate, [Validator, :string], NodesArray.by_ref
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
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
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "lib/rusty_json_schema/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec| # rubocop:disable Metrics/BlockLength
|
6
|
+
spec.name = "rusty_json_schema"
|
7
|
+
spec.version = RustyJSONSchema::VERSION
|
8
|
+
spec.authors = ["Leszek Zalewski"]
|
9
|
+
spec.email = ["leszekzalewski@fastmail.fm"]
|
10
|
+
spec.license = "MIT"
|
11
|
+
spec.homepage = "https://github.com/driv3r/rusty_json_schema"
|
12
|
+
spec.summary = "FFI wrapper around jsonschema-rs Rust library."
|
13
|
+
spec.description = <<-STR
|
14
|
+
FFI wrapper around https://github.com/Stranger6667/jsonschema-rs Rust library.
|
15
|
+
|
16
|
+
Currently during heavy development.
|
17
|
+
STR
|
18
|
+
|
19
|
+
spec.platform = Gem::Platform::CURRENT if ENV.key?("PER_PLATFORM_BUILD")
|
20
|
+
spec.required_ruby_version = Gem::Requirement.new(">= 2.5.0")
|
21
|
+
|
22
|
+
spec.metadata["allowed_push_host"] = "https://rubygems.org"
|
23
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
24
|
+
spec.metadata["source_code_uri"] = spec.homepage
|
25
|
+
spec.metadata["changelog_uri"] = "https://github.com/driv3r/rusty_json_schema/blob/main/CHANGELOG.md"
|
26
|
+
|
27
|
+
spec.files = Dir[
|
28
|
+
"lib/**/*",
|
29
|
+
"src/**/*.rs",
|
30
|
+
"rusty_json_schema.gemspec",
|
31
|
+
"Cargo.toml",
|
32
|
+
"LICENSE",
|
33
|
+
"README.md",
|
34
|
+
"ext/Rakefile",
|
35
|
+
"ext/json_schema.so.default"
|
36
|
+
]
|
37
|
+
|
38
|
+
spec.require_paths = ["lib"]
|
39
|
+
|
40
|
+
spec.extensions << "ext/Rakefile"
|
41
|
+
spec.add_runtime_dependency "thermite", "~> 0"
|
42
|
+
|
43
|
+
# Uncomment to register a new dependency of your gem
|
44
|
+
spec.add_dependency "ffi", "~> 1.14"
|
45
|
+
spec.add_dependency "json", ">= 1.0"
|
46
|
+
end
|
data/src/lib.rs
ADDED
@@ -0,0 +1,268 @@
|
|
1
|
+
extern crate libc;
|
2
|
+
|
3
|
+
use jsonschema::JSONSchema;
|
4
|
+
use serde_json::Value;
|
5
|
+
|
6
|
+
use std::ffi::{CStr, CString};
|
7
|
+
use std::os::raw::{c_char, c_uint};
|
8
|
+
|
9
|
+
/*
|
10
|
+
* Our wrapper struct for schema and schema value,
|
11
|
+
* we need to hold onto value in order to not have
|
12
|
+
* it freed up, as JSONSchema uses it as reference.
|
13
|
+
*/
|
14
|
+
pub struct Validator {
|
15
|
+
schema: &'static JSONSchema<'static>,
|
16
|
+
schema_value: &'static Value,
|
17
|
+
}
|
18
|
+
|
19
|
+
impl Validator {
|
20
|
+
/*
|
21
|
+
* With Box::leak we avoid freeing up of schema
|
22
|
+
* and schema value, we free them up separately
|
23
|
+
* in the Drop implementation
|
24
|
+
*/
|
25
|
+
fn new(schema: Value) -> Validator {
|
26
|
+
let boxed_schema: &'static Value = Box::leak(Box::new(schema));
|
27
|
+
let boxed_compile: &'static JSONSchema<'static> =
|
28
|
+
Box::leak(Box::new(JSONSchema::compile(boxed_schema).unwrap()));
|
29
|
+
|
30
|
+
Validator {
|
31
|
+
schema: boxed_compile,
|
32
|
+
schema_value: boxed_schema,
|
33
|
+
}
|
34
|
+
}
|
35
|
+
|
36
|
+
fn is_valid(&self, event: &Value) -> bool {
|
37
|
+
self.schema.is_valid(event)
|
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
|
+
}
|
51
|
+
}
|
52
|
+
|
53
|
+
impl Drop for Validator {
|
54
|
+
/*
|
55
|
+
* Free up schema with value by "materializing" them,
|
56
|
+
* otherwise they will leak memory.
|
57
|
+
*/
|
58
|
+
fn drop(&mut self) {
|
59
|
+
unsafe {
|
60
|
+
Box::from_raw(self.schema as *const _ as *mut JSONSchema);
|
61
|
+
Box::from_raw(self.schema_value as *const _ as *mut Value);
|
62
|
+
}
|
63
|
+
}
|
64
|
+
}
|
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
|
+
|
96
|
+
fn to_string(ptr: *const c_char) -> &'static CStr {
|
97
|
+
unsafe {
|
98
|
+
assert!(!ptr.is_null());
|
99
|
+
CStr::from_ptr(ptr)
|
100
|
+
}
|
101
|
+
}
|
102
|
+
|
103
|
+
#[no_mangle]
|
104
|
+
pub extern "C" fn validator_new(c_schema: *const c_char) -> *mut Validator {
|
105
|
+
let raw_schema = to_string(c_schema);
|
106
|
+
let schema = serde_json::from_slice(raw_schema.to_bytes()).unwrap();
|
107
|
+
let validator = Validator::new(schema);
|
108
|
+
|
109
|
+
Box::into_raw(Box::new(validator))
|
110
|
+
}
|
111
|
+
|
112
|
+
#[no_mangle]
|
113
|
+
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
114
|
+
pub extern "C" fn validator_free(ptr: *mut Validator) {
|
115
|
+
if ptr.is_null() {
|
116
|
+
return;
|
117
|
+
}
|
118
|
+
|
119
|
+
unsafe {
|
120
|
+
Box::from_raw(ptr);
|
121
|
+
}
|
122
|
+
}
|
123
|
+
|
124
|
+
#[no_mangle]
|
125
|
+
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
126
|
+
pub extern "C" fn validator_is_valid(ptr: *const Validator, event: *const c_char) -> bool {
|
127
|
+
let validator = unsafe {
|
128
|
+
assert!(!ptr.is_null());
|
129
|
+
&*ptr
|
130
|
+
};
|
131
|
+
|
132
|
+
let raw_event = to_string(event);
|
133
|
+
let event: Value = serde_json::from_slice(raw_event.to_bytes()).unwrap();
|
134
|
+
|
135
|
+
validator.is_valid(&event)
|
136
|
+
}
|
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
|
+
|
172
|
+
#[cfg(test)]
|
173
|
+
mod tests {
|
174
|
+
// Note this useful idiom: importing names from outer (for mod tests) scope.
|
175
|
+
use super::*;
|
176
|
+
use std::ffi::CString;
|
177
|
+
|
178
|
+
/*
|
179
|
+
* Simple sanity check if everything works together
|
180
|
+
*/
|
181
|
+
#[test]
|
182
|
+
fn test_valid_event() {
|
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);
|
201
|
+
|
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) };
|
210
|
+
|
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
|
+
];
|
216
|
+
|
217
|
+
assert_eq!(result, expectation);
|
218
|
+
|
219
|
+
validator_free(validator);
|
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
|
+
}
|
268
|
+
}
|
metadata
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rusty_json_schema
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.0
|
5
|
+
platform: x64-mingw32
|
6
|
+
authors:
|
7
|
+
- Leszek Zalewski
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2021-01-07 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: thermite
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: ffi
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.14'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.14'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: json
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.0'
|
55
|
+
description: |2
|
56
|
+
FFI wrapper around https://github.com/Stranger6667/jsonschema-rs Rust library.
|
57
|
+
|
58
|
+
Currently during heavy development.
|
59
|
+
email:
|
60
|
+
- leszekzalewski@fastmail.fm
|
61
|
+
executables: []
|
62
|
+
extensions:
|
63
|
+
- ext/Rakefile
|
64
|
+
extra_rdoc_files: []
|
65
|
+
files:
|
66
|
+
- Cargo.toml
|
67
|
+
- README.md
|
68
|
+
- ext/Rakefile
|
69
|
+
- ext/json_schema.so.default
|
70
|
+
- lib/rusty_json_schema.rb
|
71
|
+
- lib/rusty_json_schema/binding.rb
|
72
|
+
- lib/rusty_json_schema/nodes_array.rb
|
73
|
+
- lib/rusty_json_schema/validator.rb
|
74
|
+
- lib/rusty_json_schema/version.rb
|
75
|
+
- lib/tasks/thermite_dir_patch.rb
|
76
|
+
- rusty_json_schema.gemspec
|
77
|
+
- src/lib.rs
|
78
|
+
homepage: https://github.com/driv3r/rusty_json_schema
|
79
|
+
licenses:
|
80
|
+
- MIT
|
81
|
+
metadata:
|
82
|
+
allowed_push_host: https://rubygems.org
|
83
|
+
homepage_uri: https://github.com/driv3r/rusty_json_schema
|
84
|
+
source_code_uri: https://github.com/driv3r/rusty_json_schema
|
85
|
+
changelog_uri: https://github.com/driv3r/rusty_json_schema/blob/main/CHANGELOG.md
|
86
|
+
post_install_message:
|
87
|
+
rdoc_options: []
|
88
|
+
require_paths:
|
89
|
+
- lib
|
90
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
91
|
+
requirements:
|
92
|
+
- - ">="
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: 2.5.0
|
95
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
96
|
+
requirements:
|
97
|
+
- - ">="
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: '0'
|
100
|
+
requirements: []
|
101
|
+
rubyforge_project:
|
102
|
+
rubygems_version: 2.7.3
|
103
|
+
signing_key:
|
104
|
+
specification_version: 4
|
105
|
+
summary: FFI wrapper around jsonschema-rs Rust library.
|
106
|
+
test_files: []
|