rusty_json_schema 0.1.0 → 0.6.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Cargo.toml +3 -2
- data/README.md +27 -4
- data/ext/Rakefile +51 -0
- data/ext/json_schema.so.x64-mingw32.default +0 -0
- data/ext/json_schema.so.x86_64-darwin.default +0 -0
- data/ext/json_schema.so.x86_64-linux.default +0 -0
- data/lib/rusty_json_schema.rb +25 -38
- 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 +1 -1
- data/lib/tasks/thermite_dir_patch.rb +13 -0
- data/rusty_json_schema.gemspec +16 -3
- data/src/lib.rs +164 -14
- metadata +42 -14
- data/lib/ext/json_schema.d +0 -1
- 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.d +0 -1
- data/lib/ext/libjson_schema.dylib +0 -0
- data/lib/ext/libjson_schema.so +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '0898afb3388ad9f5ff7ac27fedc0bbde902f802b23a71ae4c67cd42eb6a93ab5'
|
4
|
+
data.tar.gz: '073396f70a8b35c1670b13330479dccde247cd7dd66d6d8e9482ce0e46bb60c1'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b382459eca3e4f31a77ccb4c5e9dce4d15c5f24497955299c10f1c191df079098173d7687855d8cc11c393ecc62b87a78b01f225d9ac2def2440b2c1baf2eb05
|
7
|
+
data.tar.gz: 71a88a2751f3db9e05fc1a3c90240d8ac63ff51b3878f1ee2db7d7a42f9d87415935f8f2f5d1b8b69927a17bf3dad2d799fa90e740653ad135f42d6858b89678
|
data/Cargo.toml
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
[package]
|
2
2
|
name = "json_schema"
|
3
|
-
version = "0.1
|
3
|
+
version = "0.6.1"
|
4
4
|
authors = ["Leszek Zalewski <leszekzalewski@fastmail.fm>"]
|
5
5
|
edition = "2018"
|
6
6
|
|
@@ -9,5 +9,6 @@ name = "json_schema"
|
|
9
9
|
crate-type = ["cdylib"]
|
10
10
|
|
11
11
|
[dependencies]
|
12
|
-
|
12
|
+
libc = "0.2.81"
|
13
|
+
jsonschema = "0.6.1"
|
13
14
|
serde_json = "1.0"
|
data/README.md
CHANGED
@@ -1,11 +1,15 @@
|
|
1
1
|
# RustyJSONSchema
|
2
2
|
|
3
|
-
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/rusty_json_schema.svg)](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
|
|
7
9
|
## Installation
|
8
10
|
|
11
|
+
> **NOTE**: Compilation requires openssl-dev / openssl-devel package
|
12
|
+
|
9
13
|
Add this line to your application's Gemfile:
|
10
14
|
|
11
15
|
```ruby
|
@@ -14,11 +18,15 @@ gem "rusty_json_schema"
|
|
14
18
|
|
15
19
|
And then execute:
|
16
20
|
|
17
|
-
|
21
|
+
```
|
22
|
+
$ bundle install
|
23
|
+
```
|
18
24
|
|
19
25
|
Or install it yourself as:
|
20
26
|
|
21
|
-
|
27
|
+
```
|
28
|
+
$ gem install rusty_json_schema
|
29
|
+
```
|
22
30
|
|
23
31
|
## Usage
|
24
32
|
|
@@ -32,13 +40,28 @@ Validate events like
|
|
32
40
|
|
33
41
|
```ruby
|
34
42
|
validator.valid?(event_json)
|
43
|
+
# => true/false
|
44
|
+
```
|
45
|
+
|
46
|
+
To get validation errors
|
47
|
+
|
48
|
+
```ruby
|
49
|
+
validator.validate(event_json)
|
50
|
+
# => ["invalid...", ...]
|
35
51
|
```
|
36
52
|
|
37
53
|
## Development
|
38
54
|
|
39
55
|
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
56
|
|
41
|
-
To install this gem onto your local machine, run `bundle exec rake install`.
|
57
|
+
To install this gem onto your local machine, run `bundle exec rake install`.
|
58
|
+
|
59
|
+
To release a new version:
|
60
|
+
|
61
|
+
- update version number in `version.rb` & `CHANGELOG.md`
|
62
|
+
- create GitHub release with tag being new version prefixed with `v`, i.e. for `VERSION="0.1.0"` it would be `v0.1.0`
|
63
|
+
- pull `*.gem` artifact from release build
|
64
|
+
- `gem push *.gem` in order to publish it in [rubygems.org](https://rubygems.org).
|
42
65
|
|
43
66
|
## Contributing
|
44
67
|
|
data/ext/Rakefile
ADDED
@@ -0,0 +1,51 @@
|
|
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 # rubocop:disable Metrics/BlockLength
|
12
|
+
desc "Clean up default binaries"
|
13
|
+
task :clean_binnaries do
|
14
|
+
puts "Cleaning up"
|
15
|
+
Dir["#{thermite.config.ruby_extension_path}.*.default"].each do |file|
|
16
|
+
FileUtils.rm(file)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
desc "Try to build extension if cargo is available or setup default lib"
|
21
|
+
task :build_or_default do
|
22
|
+
platform = "#{Gem::Platform.local.cpu}-#{Gem::Platform.local.os}"
|
23
|
+
default_ext_path = "#{thermite.config.ruby_extension_path}.#{platform}.default"
|
24
|
+
|
25
|
+
if thermite.cargo
|
26
|
+
profile = ENV.fetch("CARGO_PROFILE", "release")
|
27
|
+
thermite.run_cargo_rustc(profile)
|
28
|
+
|
29
|
+
FileUtils.cp(thermite.config.cargo_target_path(profile, thermite.config.cargo_shared_library),
|
30
|
+
thermite.config.ruby_extension_path)
|
31
|
+
elsif File.exist?(default_ext_path)
|
32
|
+
puts "NOTE: Defaults to pre-build binary #{default_ext_path.inspect} => your mileage may vary."
|
33
|
+
|
34
|
+
FileUtils.mv(default_ext_path,
|
35
|
+
thermite.config.ruby_extension_path)
|
36
|
+
|
37
|
+
thermite.inform_user_about_cargo
|
38
|
+
else
|
39
|
+
# Prebuild binary is not available for a given platform, install cargo to
|
40
|
+
# compile the gem
|
41
|
+
raise thermite.cargo_required_msg
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
desc "Cleanup cargo artifacts"
|
46
|
+
task :cargo_clean do
|
47
|
+
thermite.run_cargo_if_exists "clean", *thermite.cargo_manifest_path_args
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
task default: %w[thermite:build_or_default thermite:cargo_clean thermite:clean_binnaries]
|
Binary file
|
Binary file
|
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,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
|
data/rusty_json_schema.gemspec
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
require_relative "lib/rusty_json_schema/version"
|
4
4
|
|
5
|
-
Gem::Specification.new do |spec|
|
5
|
+
Gem::Specification.new do |spec| # rubocop:disable Metrics/BlockLength
|
6
6
|
spec.name = "rusty_json_schema"
|
7
7
|
spec.version = RustyJSONSchema::VERSION
|
8
8
|
spec.authors = ["Leszek Zalewski"]
|
@@ -16,17 +16,30 @@ Gem::Specification.new do |spec|
|
|
16
16
|
Currently during heavy development.
|
17
17
|
STR
|
18
18
|
|
19
|
-
spec.required_ruby_version = Gem::Requirement.new(">= 2.
|
19
|
+
spec.required_ruby_version = Gem::Requirement.new(">= 2.6.0")
|
20
20
|
|
21
21
|
spec.metadata["allowed_push_host"] = "https://rubygems.org"
|
22
22
|
spec.metadata["homepage_uri"] = spec.homepage
|
23
23
|
spec.metadata["source_code_uri"] = spec.homepage
|
24
24
|
spec.metadata["changelog_uri"] = "https://github.com/driv3r/rusty_json_schema/blob/main/CHANGELOG.md"
|
25
25
|
|
26
|
-
spec.files = Dir[
|
26
|
+
spec.files = Dir[
|
27
|
+
"lib/**/*",
|
28
|
+
"src/**/*.rs",
|
29
|
+
"rusty_json_schema.gemspec",
|
30
|
+
"Cargo.toml",
|
31
|
+
"LICENSE",
|
32
|
+
"README.md",
|
33
|
+
"ext/Rakefile",
|
34
|
+
"ext/*.default"
|
35
|
+
]
|
27
36
|
|
28
37
|
spec.require_paths = ["lib"]
|
29
38
|
|
39
|
+
spec.extensions << "ext/Rakefile"
|
40
|
+
spec.add_runtime_dependency "thermite", "~> 0"
|
41
|
+
|
30
42
|
# Uncomment to register a new dependency of your gem
|
31
43
|
spec.add_dependency "ffi", "~> 1.14"
|
44
|
+
spec.add_dependency "json", ">= 1.0"
|
32
45
|
end
|
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,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rusty_json_schema
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1
|
4
|
+
version: 0.6.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Leszek Zalewski
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-06-02 00:00:00.000000000 Z
|
12
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'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: ffi
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -24,6 +38,20 @@ dependencies:
|
|
24
38
|
- - "~>"
|
25
39
|
- !ruby/object:Gem::Version
|
26
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'
|
27
55
|
description: |2
|
28
56
|
FFI wrapper around https://github.com/Stranger6667/jsonschema-rs Rust library.
|
29
57
|
|
@@ -31,21 +59,22 @@ description: |2
|
|
31
59
|
email:
|
32
60
|
- leszekzalewski@fastmail.fm
|
33
61
|
executables: []
|
34
|
-
extensions:
|
62
|
+
extensions:
|
63
|
+
- ext/Rakefile
|
35
64
|
extra_rdoc_files: []
|
36
65
|
files:
|
37
66
|
- Cargo.toml
|
38
67
|
- README.md
|
39
|
-
-
|
40
|
-
-
|
41
|
-
-
|
42
|
-
-
|
43
|
-
- lib/ext/json_schema.pdb
|
44
|
-
- lib/ext/libjson_schema.d
|
45
|
-
- lib/ext/libjson_schema.dylib
|
46
|
-
- lib/ext/libjson_schema.so
|
68
|
+
- ext/Rakefile
|
69
|
+
- ext/json_schema.so.x64-mingw32.default
|
70
|
+
- ext/json_schema.so.x86_64-darwin.default
|
71
|
+
- ext/json_schema.so.x86_64-linux.default
|
47
72
|
- lib/rusty_json_schema.rb
|
73
|
+
- lib/rusty_json_schema/binding.rb
|
74
|
+
- lib/rusty_json_schema/nodes_array.rb
|
75
|
+
- lib/rusty_json_schema/validator.rb
|
48
76
|
- lib/rusty_json_schema/version.rb
|
77
|
+
- lib/tasks/thermite_dir_patch.rb
|
49
78
|
- rusty_json_schema.gemspec
|
50
79
|
- src/lib.rs
|
51
80
|
homepage: https://github.com/driv3r/rusty_json_schema
|
@@ -64,15 +93,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
64
93
|
requirements:
|
65
94
|
- - ">="
|
66
95
|
- !ruby/object:Gem::Version
|
67
|
-
version: 2.
|
96
|
+
version: 2.6.0
|
68
97
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
69
98
|
requirements:
|
70
99
|
- - ">="
|
71
100
|
- !ruby/object:Gem::Version
|
72
101
|
version: '0'
|
73
102
|
requirements: []
|
74
|
-
|
75
|
-
rubygems_version: 2.7.3
|
103
|
+
rubygems_version: 3.0.1
|
76
104
|
signing_key:
|
77
105
|
specification_version: 4
|
78
106
|
summary: FFI wrapper around jsonschema-rs Rust library.
|
data/lib/ext/json_schema.d
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
D:\a\rusty_json_schema\rusty_json_schema\target\x86_64-pc-windows-msvc\release\json_schema.dll: D:\a\rusty_json_schema\rusty_json_schema\src\lib.rs
|
data/lib/ext/json_schema.dll
DELETED
Binary file
|
data/lib/ext/json_schema.dll.exp
DELETED
Binary file
|
data/lib/ext/json_schema.dll.lib
DELETED
Binary file
|
data/lib/ext/json_schema.pdb
DELETED
Binary file
|
data/lib/ext/libjson_schema.d
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
/home/runner/work/rusty_json_schema/rusty_json_schema/target/x86_64-unknown-linux-gnu/release/libjson_schema.so: /home/runner/work/rusty_json_schema/rusty_json_schema/src/lib.rs
|
Binary file
|
data/lib/ext/libjson_schema.so
DELETED
Binary file
|