nakischema 0.0.2 → 0.1.2

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 (4) hide show
  1. checksums.yaml +4 -4
  2. data/lib/nakischema.rb +65 -6
  3. data/nakischema.gemspec +1 -1
  4. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 23e9302b311123a5b0837d868887c752af34a976
4
- data.tar.gz: 275eb8ded8c32e65f1daa4daab04c559937f1b58
3
+ metadata.gz: e2f43f84837afad700ae5e280e871caab6c8ef85
4
+ data.tar.gz: 83e3763773cf849ffa066bc2ad333b5c65e4ff5e
5
5
  SHA512:
6
- metadata.gz: 30f2f5ca6da4eed2d5d94a1e967f260e561343db487d14b0114b2f77e40da3d71b4f3c7356520390678746f49fe459f45b7c01f70ddf4f29ab6506ec267d654e
7
- data.tar.gz: aecc915fd810136e9465f9921f8878005b3ebc6edb1d4d0f101f1cfc5103b85fa8c79139f6bec9dba6aa0c1dc182bc10d879a5c807cce72356d12c1f3e2a5e6a
6
+ metadata.gz: 28750ccd6f46dcf3dd4d8e2a8edd98eb5477d48d198e4f93d36fff73d063e8e7d5453eaf12042ee5a939382804036bae2d156f8436d881a48a89c1d2bd20dfe9
7
+ data.tar.gz: 3d8a8e2da496705ae17582add987165aa98161ebbe233013c45739415e804ad6b87c3b26ba48332255d4f319f77825ae31064e9a27c106a0aa9c2d11a4cea14f
data/lib/nakischema.rb CHANGED
@@ -1,25 +1,33 @@
1
1
  module Nakischema
2
2
  Error = Class.new RuntimeError
3
+
3
4
  def self.validate object, schema, path = []
4
5
  raise_with_path = lambda do |msg, _path = path|
5
6
  raise Error.new "#{msg}#{" (at #{_path})" unless _path.empty?}"
6
7
  end
7
8
  # TODO: maybe move '(at ...)' to the beginning
8
9
  case schema
10
+ when NilClass, TrueClass, FalseClass, String, Symbol ; raise_with_path.call "expected #{schema.inspect} != #{object.inspect}" unless schema == object
11
+ # TODO: maybe deprecate the NilClass, TrueClass, FalseClass since they can be asserted via the next case branch
12
+ when Class ; raise_with_path.call "expected #{schema } != #{object.class }" unless schema === object
13
+ when Regexp ; raise_with_path.call "expected #{schema } != #{object.inspect}" unless schema === object
14
+ when Range ; raise_with_path.call "expected #{schema } != #{object }" unless schema.include? object
9
15
  when Hash
10
16
  raise_with_path.call "expected Hash != #{object.class}" unless object.is_a? Hash unless (schema.keys & %i{ keys each_key each_value }).empty?
11
17
  raise_with_path.call "expected Array != #{object.class}" unless object.is_a? Array unless (schema.keys & %i{ size }).empty?
12
18
  schema.each do |k, v|
13
19
  case k
14
- # when :keys_sorted ; raise_with_path.call "expected explicit keys #{v} != #{object.keys.sort}" unless v == object.keys.sort
15
20
  when :size ; raise_with_path.call "expected explicit size #{v} != #{object.size}" unless v.include? object.size
16
21
  # when Fixnum
17
22
  # raise_with_path.call "expected Array != #{object.class}" unless object.is_a? Array
18
23
  # validate object[k], v, [*path, :"##{k}"]
19
24
  when :keys ; validate object.keys, v, [*path, :keys]
25
+ when :values ; validate object.values, v, [*path, :values]
26
+ when :keys_sorted ; validate object.keys.sort, v, [*path, :keys_sorted]
20
27
  when :hash_opt ; v.each{ |k, v| validate object.fetch(k), v, [*path, k] if object.key? k }
21
28
  when :hash_req ; v.each{ |k, v| validate object.fetch(k), v, [*path, k] }
22
- when :hash ; raise_with_path.call "expected implicit keys #{v.keys} != #{object.keys.sort}" unless v.keys.sort == object.keys.sort
29
+ when :hash ; raise_with_path.call "expected Hash != #{object.class}" unless object.is_a? Hash
30
+ raise_with_path.call "expected implicit keys #{v.keys} != #{object.keys.sort}" unless v.keys.sort == object.keys.sort
23
31
  v.each{ |k, v| validate object.fetch(k), v, [*path, k] }
24
32
  when :each_key ; object.keys.each_with_index{ |k, i| validate k, v, [*path, :"key##{i}"] }
25
33
  when :each_value ; object.values.each_with_index{ |v_, i| validate v_, v, [*path, :"value##{i}"] }
@@ -49,13 +57,10 @@ module Nakischema
49
57
  raise_with_path.call "unsupported rule #{k.inspect}"
50
58
  end
51
59
  end
52
- when NilClass, TrueClass, FalseClass, String, Symbol ; raise_with_path.call "expected #{schema.inspect} != #{object.inspect}" unless schema == object
53
- when Regexp ; raise_with_path.call "expected #{schema } != #{object.inspect}" unless schema === object
54
- when Range ; raise_with_path.call "expected #{schema } != #{object }" unless schema.include? object
55
60
  when Array
56
61
  if schema.map(&:class) == [Array]
57
62
  raise_with_path.call "expected Array != #{object.class}" unless object.is_a? Array
58
- raise_with_path.call "expected implicit size #{schema[0].size} != #{object.size}" unless schema[0].size == object.size
63
+ raise_with_path.call "expected implicit size #{schema[0].size} != #{object.size} for #{object.inspect}" unless schema[0].size == object.size
59
64
  object.zip(schema[0]).each_with_index{ |(o, v), i| validate o, v, [*path, :"##{i}"] }
60
65
  else
61
66
  results = schema.lazy.with_index.map do |v, i|
@@ -74,4 +79,58 @@ module Nakischema
74
79
  raise_with_path.call "unsupported rule class #{schema.class}"
75
80
  end
76
81
  end
82
+
83
+ def self.validate_oga_xml object, schema, path = []
84
+ raise_with_path = lambda do |msg, _path = path|
85
+ raise Error.new "#{msg}#{" (at #{_path})" unless _path.empty?}"
86
+ end
87
+ case schema
88
+ when Hash
89
+ schema.each do |k, v|
90
+ case k
91
+ when :size ; raise_with_path.call "expected explicit size #{v} != #{object.size}" unless v.include? object.size
92
+ when :text ; raise_with_path.call "expected text #{v.inspect} != #{object.text.inspect}" unless v == object.text
93
+ when :each ; raise_with_path.call "expected iterable != #{object.class}" unless object.respond_to? :each_with_index
94
+ object.each_with_index{ |e, i| validate_oga_xml e, v, [*path, :"##{i}"] }
95
+ when :exact ; children = object.xpath "./*"
96
+ names = children.map(&:name).uniq
97
+ raise_with_path.call "expected implicit children #{v.keys} != #{names}" unless v.keys == names
98
+ v.each do |k, v|
99
+ selected = children.select{ |_| _.name == k }
100
+ validate_oga_xml selected, v, [*path, k]
101
+ end
102
+ when :children ; v.each{ |k, v| validate_oga_xml object.xpath(k.start_with?("./") ? k : "./#{k}"), v, [*path, k] }
103
+ when :attr_req ; v.each{ |k, v| raise_with_path.call "expected #{v} != #{object[k]}", [*path, k] unless v === object[k] }
104
+ when :assertions
105
+ v.each_with_index do |assertion, i|
106
+ begin
107
+ raise Error.new "custom assertion failed" unless assertion.call object, [*path, :"assertion##{i}"]
108
+ rescue Error => e
109
+ raise_with_path.call e, [*path, :"assertion##{i}"]
110
+ end
111
+ end
112
+ else
113
+ raise_with_path.call "unsupported rule #{k.inspect}"
114
+ end
115
+ end
116
+ when Array
117
+ if schema.map(&:class) == [Array]
118
+ raise_with_path.call "expected implicit size #{schema[0].size} != #{object.size} for #{object.inspect}" unless schema[0].size == object.size
119
+ object.zip(schema[0]).each_with_index{ |(o, v), i| validate_oga_xml o, v, [*path, :"##{i}"] }
120
+ else
121
+ results = schema.lazy.with_index.map do |v, i|
122
+ begin
123
+ validate_oga_xml object, v, [*path, :"variant##{i}"]
124
+ nil
125
+ rescue Error => e
126
+ e
127
+ end
128
+ end
129
+ raise Error.new "expected at least one of #{schema.size} rules to match the #{object.inspect}, errors:\n" +
130
+ results.force.compact.map{ |_| _.to_s.gsub(/^/, " ") }.join("\n") if results.all?
131
+ end
132
+ else
133
+ raise_with_path.call "unsupported rule class #{schema.class}"
134
+ end
135
+ end
77
136
  end
data/nakischema.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |spec|
2
2
  spec.name = "nakischema"
3
- spec.version = "0.0.2"
3
+ spec.version = "0.1.2"
4
4
  spec.summary = "compact yet powerful arbitrary nested objects validator"
5
5
  spec.description = "The most compact yet powerful arbitrary nested objects validator. Especially handy to validate JSONs."
6
6
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nakischema
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Victor Maslov aka Nakilon
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-08-14 00:00:00.000000000 Z
11
+ date: 2021-09-11 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: The most compact yet powerful arbitrary nested objects validator. Especially
14
14
  handy to validate JSONs.