nakischema 0.0.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.
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: []