rusty_json_schema 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: e89b25e8e45ded120281d3b9b6af8a85bf5b8d0cb4f86b2f339485d629cf4dfd
4
+ data.tar.gz: 1c6859709cd625af4184235dc09b1dfdaf05b8d0aca6fe8998c13c8bc11c1c4b
5
+ SHA512:
6
+ metadata.gz: 27da18c9402b2f91c92a75f97f31ad0eb9761aa322634e79ac4dd4b735bdb1d9e138821991a41c03648be01cc8ec1f15a13868cf96f65421b1d6a00f2bac226f
7
+ data.tar.gz: c09eaf66fce3eb9daa15c9ab78a23fa82276a7aeb2176ca23579936ff6bf798e7990731937662fc63c0d42ce7a6c59c45efbc4a5509722c84b3be16d1b3a481b
@@ -0,0 +1,13 @@
1
+ [package]
2
+ name = "json_schema"
3
+ version = "0.1.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
+ jsonschema = "0.4.3"
13
+ serde_json = "1.0"
@@ -0,0 +1,53 @@
1
+ # RustyJSONSchema
2
+
3
+ FFI wrapper around [`jsonschema`](https://github.com/Stranger6667/jsonschema-rs) rust library. Props go to original project.
4
+
5
+ Currently during heavy development.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem "rusty_json_schema"
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle install
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install rusty_json_schema
22
+
23
+ ## Usage
24
+
25
+ Initialize schema validator
26
+
27
+ ```ruby
28
+ validator = RustyJSONSchema.build(json_schema)
29
+ ```
30
+
31
+ Validate events like
32
+
33
+ ```ruby
34
+ validator.valid?(event_json)
35
+ ```
36
+
37
+ ## Development
38
+
39
+ 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
+
41
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
42
+
43
+ ## Contributing
44
+
45
+ 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).
46
+
47
+ ## License
48
+
49
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
50
+
51
+ ## Code of Conduct
52
+
53
+ 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).
@@ -0,0 +1 @@
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
Binary file
Binary file
@@ -0,0 +1 @@
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
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "ffi"
4
+
5
+ require_relative "rusty_json_schema/version"
6
+
7
+ # JSON Schema validation
8
+ #
9
+ # ## Example
10
+ #
11
+ # validator = RustyJSONSchema.build(schema) # where schema is a json string of the schema
12
+ # validator.valid?(event) # where event is a json string of schema
13
+ # # => true/false
14
+ #
15
+ module RustyJSONSchema
16
+
17
+ def self.build(schema)
18
+ RustyJSONSchema::Validator::Binding.new(schema)
19
+ end
20
+
21
+ class Error < StandardError; end
22
+
23
+ # Handles release of the pointer automatically
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
28
+
29
+ # Custom GC flow for our validator, freeing
30
+ # the object within Rust
31
+ #
32
+ def self.release(pointer)
33
+ Binding.free(pointer)
34
+ end
35
+
36
+ # Simple validation without actual error messages
37
+ #
38
+ def valid?(event)
39
+ Binding.is_valid(self, event)
40
+ end
41
+
42
+ # FFI container for our library.
43
+ #
44
+ module Binding
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
+
60
+ end
61
+
62
+ end
63
+
64
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RustyJSONSchema
4
+
5
+ VERSION = "0.1.0"
6
+
7
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/rusty_json_schema/version"
4
+
5
+ Gem::Specification.new do |spec|
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.required_ruby_version = Gem::Requirement.new(">= 2.5.0")
20
+
21
+ spec.metadata["allowed_push_host"] = "https://rubygems.org"
22
+ spec.metadata["homepage_uri"] = spec.homepage
23
+ spec.metadata["source_code_uri"] = spec.homepage
24
+ spec.metadata["changelog_uri"] = "https://github.com/driv3r/rusty_json_schema/blob/main/CHANGELOG.md"
25
+
26
+ spec.files = Dir["lib/**/*", "src/**/*.rs", "rusty_json_schema.gemspec", "Cargo.toml", "LICENSE", "README.md"]
27
+
28
+ spec.require_paths = ["lib"]
29
+
30
+ # Uncomment to register a new dependency of your gem
31
+ spec.add_dependency "ffi", "~> 1.14"
32
+ end
@@ -0,0 +1,118 @@
1
+ use jsonschema::JSONSchema;
2
+ use serde_json::Value;
3
+
4
+ use std::ffi::CStr;
5
+ use std::os::raw::c_char;
6
+
7
+ /*
8
+ * Our wrapper struct for schema and schema value,
9
+ * we need to hold onto value in order to not have
10
+ * it freed up, as JSONSchema uses it as reference.
11
+ */
12
+ pub struct Validator {
13
+ schema: &'static JSONSchema<'static>,
14
+ schema_value: &'static Value,
15
+ }
16
+
17
+ impl Validator {
18
+ /*
19
+ * With Box::leak we avoid freeing up of schema
20
+ * and schema value, we free them up separately
21
+ * in the Drop implementation
22
+ */
23
+ fn new(schema: Value) -> Validator {
24
+ let boxed_schema: &'static Value = Box::leak(Box::new(schema));
25
+ let boxed_compile: &'static JSONSchema<'static> = Box::leak(Box::new(JSONSchema::compile(boxed_schema).unwrap()));
26
+
27
+ Validator {
28
+ schema: boxed_compile,
29
+ schema_value: boxed_schema,
30
+ }
31
+ }
32
+
33
+ fn is_valid(&self, event: &Value) -> bool {
34
+ self.schema.is_valid(event)
35
+ }
36
+ }
37
+
38
+ impl Drop for Validator {
39
+ /*
40
+ * Free up schema with value by "materializing" them,
41
+ * otherwise they will leak memory.
42
+ */
43
+ fn drop(&mut self) {
44
+ unsafe {
45
+ Box::from_raw(self.schema as *const _ as *mut JSONSchema);
46
+ Box::from_raw(self.schema_value as *const _ as *mut Value);
47
+ }
48
+ }
49
+ }
50
+
51
+ fn to_string(ptr: *const c_char) -> &'static CStr {
52
+ unsafe {
53
+ assert!(!ptr.is_null());
54
+ CStr::from_ptr(ptr)
55
+ }
56
+ }
57
+
58
+ #[no_mangle]
59
+ pub extern "C" fn validator_new(c_schema: *const c_char) -> *mut Validator {
60
+ let raw_schema = to_string(c_schema);
61
+ let schema = serde_json::from_slice(raw_schema.to_bytes()).unwrap();
62
+ let validator = Validator::new(schema);
63
+
64
+ Box::into_raw(Box::new(validator))
65
+ }
66
+
67
+ #[no_mangle]
68
+ pub extern "C" fn validator_free(ptr: *mut Validator) {
69
+ if ptr.is_null() {
70
+ return;
71
+ }
72
+
73
+ unsafe {
74
+ Box::from_raw(ptr);
75
+ }
76
+ }
77
+
78
+ #[no_mangle]
79
+ pub extern "C" fn validator_is_valid(ptr: *const Validator, event: *const c_char) -> bool {
80
+ let validator = unsafe {
81
+ assert!(!ptr.is_null());
82
+ &*ptr
83
+ };
84
+
85
+ let raw_event = to_string(event);
86
+ let event: Value = serde_json::from_slice(raw_event.to_bytes()).unwrap();
87
+
88
+ validator.is_valid(&event)
89
+ }
90
+
91
+ #[cfg(test)]
92
+ mod tests {
93
+ // Note this useful idiom: importing names from outer (for mod tests) scope.
94
+ use super::*;
95
+ use std::ffi::CString;
96
+ use std::{thread, time};
97
+
98
+ /*
99
+ * Simple sanity check if everything works together
100
+ */
101
+ #[test]
102
+ fn test_valid_event() {
103
+ let schema = CString::new("{\"$schema\":\"http://json-schema.org/draft-07/schema#\",\"type\":\"array\",\"items\":[{\"type\":\"number\",\"exclusiveMaximum\":10}]}").unwrap();
104
+ let valid_event = CString::new("[9]").unwrap();
105
+ let invalid_event = CString::new("[22]").unwrap();
106
+
107
+ let c_schema_ptr: *const c_char = schema.as_ptr();
108
+ let c_valid_event_ptr: *const c_char = valid_event.as_ptr();
109
+ let c_invalid_event_ptr: *const c_char = invalid_event.as_ptr();
110
+
111
+ let validator = validator_new(c_schema_ptr);
112
+
113
+ assert!(validator_is_valid(validator, c_valid_event_ptr));
114
+ assert!(!validator_is_valid(validator, c_invalid_event_ptr));
115
+
116
+ validator_free(validator);
117
+ }
118
+ }
metadata ADDED
@@ -0,0 +1,79 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rusty_json_schema
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Leszek Zalewski
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-12-28 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: ffi
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.14'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.14'
27
+ description: |2
28
+ FFI wrapper around https://github.com/Stranger6667/jsonschema-rs Rust library.
29
+
30
+ Currently during heavy development.
31
+ email:
32
+ - leszekzalewski@fastmail.fm
33
+ executables: []
34
+ extensions: []
35
+ extra_rdoc_files: []
36
+ files:
37
+ - Cargo.toml
38
+ - README.md
39
+ - lib/ext/json_schema.d
40
+ - lib/ext/json_schema.dll
41
+ - lib/ext/json_schema.dll.exp
42
+ - lib/ext/json_schema.dll.lib
43
+ - lib/ext/json_schema.pdb
44
+ - lib/ext/libjson_schema.d
45
+ - lib/ext/libjson_schema.dylib
46
+ - lib/ext/libjson_schema.so
47
+ - lib/rusty_json_schema.rb
48
+ - lib/rusty_json_schema/version.rb
49
+ - rusty_json_schema.gemspec
50
+ - src/lib.rs
51
+ homepage: https://github.com/driv3r/rusty_json_schema
52
+ licenses:
53
+ - MIT
54
+ metadata:
55
+ allowed_push_host: https://rubygems.org
56
+ homepage_uri: https://github.com/driv3r/rusty_json_schema
57
+ source_code_uri: https://github.com/driv3r/rusty_json_schema
58
+ changelog_uri: https://github.com/driv3r/rusty_json_schema/blob/main/CHANGELOG.md
59
+ post_install_message:
60
+ rdoc_options: []
61
+ require_paths:
62
+ - lib
63
+ required_ruby_version: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: 2.5.0
68
+ required_rubygems_version: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: '0'
73
+ requirements: []
74
+ rubyforge_project:
75
+ rubygems_version: 2.7.3
76
+ signing_key:
77
+ specification_version: 4
78
+ summary: FFI wrapper around jsonschema-rs Rust library.
79
+ test_files: []