nakischema 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (5) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/lib/nakischema.rb +70 -0
  4. data/nakischema.gemspec +13 -0
  5. metadata +48 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 1dd008df051c38e237c7f65fe70c0680eb06c407
4
+ data.tar.gz: ff26282070eaad84c5d5d628bc7868b7857c1b9a
5
+ SHA512:
6
+ metadata.gz: ac740957dfad68d5527fe0e0a1c70adb2169563e61b922ec5660a8b298947702503568f764128a8f9f89ac87a0cfa4018490b813d4a938dea43b28b149797870
7
+ data.tar.gz: 2db4bc15ed4f118373d621890c0351f015ce337e6ac89ad0fe8e6914090169739bb9fe437d830c98fcf22ca93749cc5616cf6bf8c02ce930fb4ea3058ae398aa
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2021 Victor Maslov
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/lib/nakischema.rb ADDED
@@ -0,0 +1,70 @@
1
+ module Nakischema
2
+ Error = Class.new RuntimeError
3
+ def self.validate object, schema, path = []
4
+ raise_with_path = lambda do |msg|
5
+ raise Error.new "#{msg}#{" (at #{path})" unless path.empty?}"
6
+ end
7
+ case schema
8
+ when Hash
9
+ raise_with_path.call "expected Hash != #{object.class}" unless object.is_a? Hash unless (schema.keys & %i{ keys_sorted keys values }).empty?
10
+ raise_with_path.call "expected Array != #{object.class}" unless object.is_a? Array unless (schema.keys & %i{ size }).empty?
11
+ schema.each do |k, v|
12
+ case k
13
+ # when :keys_sorted ; raise_with_path.call "expected explicit keys #{v} != #{object.keys.sort}" unless v == object.keys.sort
14
+ when :size ; raise_with_path.call "expected explicit size #{v} != #{object.size}" unless v.include? object.size
15
+ # when Fixnum
16
+ # raise_with_path.call "expected Array != #{object.class}" unless object.is_a? Array
17
+ # validate object[k], v, [*path, "##{k}"]
18
+ when :keys ; validate object.keys, v, [*path, :keys]
19
+ when :hash_opt ; v.each{ |k, v| validate object[k], v, [*path, k] if object.key? k }
20
+ when :hash
21
+ raise_with_path.call "expected implicit keys #{v} != #{object.keys.sort}" unless v.keys.sort == object.keys.sort
22
+ v.each{ |k, v| validate object.fetch(k), v, [*path, k] }
23
+ when :each_key ; object.keys.each_with_index{ |k, i| validate k, v, [*path, :"key##{i}"] }
24
+ when :each_value ; object.values.each_with_index{ |v_, i| validate v_, v, [*path, :"value##{i}"] }
25
+ when :each
26
+ raise_with_path.call "expected iterable != #{object.class}" unless object.respond_to? :each_with_index
27
+ object.each_with_index{ |e, i| validate e, v, [*path, :"##{i}"] }
28
+ # when :case
29
+ # raise_with_path.call "expected at least one of #{v.size} cases to match the #{object.inspect}" if v.map.with_index do |(k, v), i|
30
+ # next if begin
31
+ # validate object, k
32
+ # nil
33
+ # rescue Error => e
34
+ # e
35
+ # end
36
+ # validate object, v, [*path, :"case##{i}"]
37
+ # true
38
+ # end.none?
39
+ when :assertions ; v.each_with_index{ |assertion, i| raise_with_path.call "custom assertion failed" unless assertion.call object, [*path, :"assertion##{i}"] }
40
+ else ; raise_with_path.call "unsupported rule #{k.inspect}"
41
+ end
42
+ end
43
+ when NilClass, TrueClass, FalseClass, String ; raise_with_path.call "expected #{schema.inspect} != #{object.inspect}" unless schema == object
44
+ when Regexp ; raise_with_path.call "expected #{schema } != #{object.inspect}" unless schema === object
45
+ when Range ; raise_with_path.call "expected #{schema } != #{object }" unless schema.include? object
46
+ when Array
47
+ if schema.map(&:class) == [Array]
48
+ raise_with_path.call "expected Array != #{object.class}" unless object.is_a? Array
49
+ raise_with_path.call "expected implicit size #{schema[0].size} != #{object.size}" unless schema[0].size == object.size
50
+ object.zip(schema[0]).each_with_index do |(o, v), i|
51
+ validate o, v, [*path, :"##{i}"]
52
+ end
53
+ else
54
+ results = schema.lazy.with_index.map do |v, i|
55
+ # raise_with_path.call "unsupported nested Array" if v.is_a? Array
56
+ begin
57
+ validate object, v, [*path, "variant##{i}"]
58
+ nil
59
+ rescue Error => e
60
+ e
61
+ end
62
+ end
63
+ raise_with_path.call \
64
+ "expected at least one of #{schema.size} rules to match the #{object.inspect}, errors:\n" +
65
+ results.force.compact.map{ |_| _.to_s.gsub(/^/, " ") }.join("\n") if results.all?
66
+ end
67
+ else ; raise_with_path.call "unsupported rule class #{schema.class}"
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,13 @@
1
+ Gem::Specification.new do |spec|
2
+ spec.name = "nakischema"
3
+ spec.version = "0.0.0"
4
+ spec.summary = "compact yet powerful arbitrary nested objects validator"
5
+ spec.description = "The most compact yet powerful arbitrary nested objects validator. Especially handy to validate JSONs."
6
+
7
+ spec.author = "Victor Maslov aka Nakilon"
8
+ spec.email = "nakilon@gmail.com"
9
+ spec.license = "MIT"
10
+ spec.metadata = {"source_code_uri" => "https://github.com/nakilon/nakischema"}
11
+
12
+ spec.files = %w{ LICENSE nakischema.gemspec lib/nakischema.rb }
13
+ end
metadata ADDED
@@ -0,0 +1,48 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: nakischema
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Victor Maslov aka Nakilon
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-08-14 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: The most compact yet powerful arbitrary nested objects validator. Especially
14
+ handy to validate JSONs.
15
+ email: nakilon@gmail.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - LICENSE
21
+ - lib/nakischema.rb
22
+ - nakischema.gemspec
23
+ homepage:
24
+ licenses:
25
+ - MIT
26
+ metadata:
27
+ source_code_uri: https://github.com/nakilon/nakischema
28
+ post_install_message:
29
+ rdoc_options: []
30
+ require_paths:
31
+ - lib
32
+ required_ruby_version: !ruby/object:Gem::Requirement
33
+ requirements:
34
+ - - ">="
35
+ - !ruby/object:Gem::Version
36
+ version: '0'
37
+ required_rubygems_version: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ requirements: []
43
+ rubyforge_project:
44
+ rubygems_version: 2.5.2.3
45
+ signing_key:
46
+ specification_version: 4
47
+ summary: compact yet powerful arbitrary nested objects validator
48
+ test_files: []