emery 0.0.1 → 0.0.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8dc449ad3ba135140479a6711b016e63bfc30f9fd6dcf6dba8ff78ee71208a6a
4
- data.tar.gz: 9c2f86bde90521cfa5adb78eda8ceef5504c2fbcf44de558cf2450c550cea96e
3
+ metadata.gz: e7526be75b8c44c624947657c22214dd7715170e1bbdb8b46a8369a6ca66d4fc
4
+ data.tar.gz: 5483955dd2c563ca2c6c04662aea8bc1f9b4a5e34817b9d60a046afa32ca5a04
5
5
  SHA512:
6
- metadata.gz: e9695fe9eeed44ad9d3bc33e1dc92ae4de5a31e024c7fa9ba1fa34dbd3df554cf5cd73e9634dbaec1246ca80b8ac536fd1020b129ef26d9973512c34ca77b920
7
- data.tar.gz: 8f7b8961c1c39cf2a354163725bd1fc761e620627ebbb73cb1dd91c7d5746bdc6fd937ccc17fa2bf70ef7af826dd0eb60f09102a4b27ab7f6cf1343633686ecf
6
+ metadata.gz: e1e408199c42d0c877c1ca9be978f698357449ac9f4c909c6157ec190bfb83f19434184e68bf7ab6cf96b93007e6658f1eae1f744c57a97d8fae0231eed03a76
7
+ data.tar.gz: 80f702c3cd1bd7edd8359a03576519db0002efcedd3db144ef1c3e94192ccd6fb129dd0ac8a25177f9d9dd96f016f3cf84c4237e69fe5d2e15c12f2790530456
data/lib/emery/jsoner.rb CHANGED
@@ -76,6 +76,31 @@ module Emery
76
76
  end
77
77
  end
78
78
 
79
+ T::UnionType.class_eval do
80
+ def jsoner_deserialize(json_value)
81
+ if !json_value.is_a?(Hash)
82
+ raise JsonerError.new("JSON value type #{json_value.class} is not Hash")
83
+ end
84
+ if json_value.keys.length != 1
85
+ raise JsonerError.new("JSON value #{json_value} should have only one key to represent union type, found #{json_value.keys.length}")
86
+ end
87
+ case_key = json_value.keys[0]
88
+ if not cases.key? case_key.to_sym
89
+ raise JsonerError.new("JSON key '#{case_key}' does not match any case in union type #{self}")
90
+ end
91
+ type = cases[case_key.to_sym]
92
+ case_json_value = json_value[case_key]
93
+ return Jsoner.deserialize(type, case_json_value)
94
+ end
95
+ def jsoner_serialize(value)
96
+ T.check(self, value)
97
+ type = types.find {|t| T.instance_of?(t, value) }
98
+ case_key = cases.key(type)
99
+ result = { case_key => Jsoner.serialize(type, value) }
100
+ result
101
+ end
102
+ end
103
+
79
104
  T::Nilable.class_eval do
80
105
  def jsoner_deserialize(json_value)
81
106
  if json_value != nil
data/lib/emery/type.rb CHANGED
@@ -42,20 +42,27 @@ module Emery
42
42
  "Any[#{types.map { |t| t.to_s}.join(', ')}]"
43
43
  end
44
44
  def check(value)
45
- types.each do |type|
46
- begin
47
- T.check(type, value)
48
- return
49
- rescue TypeError
50
- end
45
+ type = types.find {|t| T.instance_of?(t, value) }
46
+ if type == nil
47
+ raise TypeError.new("Value '#{value.inspect.to_s}' type is #{value.class} - any of #{@types.map { |t| t.to_s}.join(', ')} required")
51
48
  end
52
- raise TypeError.new("Value '#{value.inspect.to_s}' type is #{value.class} - any of #{@types.map { |t| t.to_s}.join(', ')} required")
53
49
  end
54
50
  def ==(other)
55
51
  T.instance_of?(AnyType, other) and (self.types - other.types).empty?
56
52
  end
57
53
  end
58
54
 
55
+ class UnionType < AnyType
56
+ attr_reader :cases
57
+ def initialize(cases)
58
+ @cases = cases
59
+ super(*cases.values)
60
+ end
61
+ def to_s
62
+ "Union[#{cases.map { |k, t| "#{k}: #{t}"}.join(', ')}]"
63
+ end
64
+ end
65
+
59
66
  class ArrayType
60
67
  attr_reader :item_type
61
68
  def initialize(item_type)
@@ -159,6 +166,10 @@ module Emery
159
166
  AnyType.new(*typdefs)
160
167
  end
161
168
 
169
+ def T.union(*cases)
170
+ UnionType.new(*cases)
171
+ end
172
+
162
173
  def T.check_var(var_name, type, value)
163
174
  begin
164
175
  check(type, value)
data/test/jsoner_test.rb CHANGED
@@ -216,13 +216,13 @@ module Emery
216
216
  end
217
217
 
218
218
  class AnyDeserialization < Test::Unit::TestCase
219
- def test_deserialize_any
219
+ def test_deserialize
220
220
  data = Jsoner.from_json(T.any(String, Integer), '"the string"')
221
221
  T.check(T.any(String, Integer), data)
222
222
  assert_equal "the string", data, "Should parse any type"
223
223
  end
224
224
 
225
- def test_deserialize_any_fail
225
+ def test_deserialize_fail
226
226
  assert_raise JsonerError do
227
227
  Jsoner.from_json(T.any(Integer, Float), '"the string"')
228
228
  end
@@ -230,10 +230,31 @@ module Emery
230
230
  end
231
231
 
232
232
  class AnySerialization < Test::Unit::TestCase
233
- def test_serialize_any
233
+ def test_serialize
234
234
  data = Jsoner.to_json(T.any(String, Integer), "the string")
235
235
  T.check(T.any(String, Integer), data)
236
236
  assert_equal '"the string"', data, "Should serialize any type"
237
237
  end
238
238
  end
239
+
240
+ class UnionDeserialization < Test::Unit::TestCase
241
+ def test_deserialize
242
+ data = Jsoner.from_json(T.union(str: String, int: Integer), '{"str":"the string"}')
243
+ T.check(T.union(str: String, int: Integer), data)
244
+ assert_equal "the string", data, "Should parse union type"
245
+ end
246
+
247
+ def test_deserialize_any_fail
248
+ assert_raise JsonerError do
249
+ Jsoner.from_json(T.union(str: String, int: Integer), '{"bool":true}')
250
+ end
251
+ end
252
+ end
253
+
254
+ class UnionSerialization < Test::Unit::TestCase
255
+ def test_serialize
256
+ data = Jsoner.to_json(T.union(str: String, int: Integer), "the string")
257
+ assert_equal '{"str":"the string"}', data, "Should serialize union type with wrapping object"
258
+ end
259
+ end
239
260
  end
data/test/type_test.rb CHANGED
@@ -70,6 +70,28 @@ module Emery
70
70
  end
71
71
  end
72
72
 
73
+ class TypeToString < Test::Unit::TestCase
74
+ def test_nilable
75
+ assert_equal "Nilable[Integer]", T.nilable(Integer).to_s
76
+ end
77
+
78
+ def test_array
79
+ assert_equal "Array[Integer]", T.array(Integer).to_s
80
+ end
81
+
82
+ def test_hash
83
+ assert_equal "Hash[String, Integer]", T.hash(String, Integer).to_s
84
+ end
85
+
86
+ def test_any
87
+ assert_equal "Any[String, Integer]", T.any(String, Integer).to_s
88
+ end
89
+
90
+ def test_union
91
+ assert_equal "Union[str: String, int: Integer]", T.union(str: String, int: Integer).to_s
92
+ end
93
+ end
94
+
73
95
  class TypeCheck < Test::Unit::TestCase
74
96
  def test_nil
75
97
  assert_equal nil, T.check(NilClass, nil)
@@ -182,4 +204,17 @@ module Emery
182
204
  end
183
205
  end
184
206
  end
207
+
208
+ class TypeCheckUnion < Test::Unit::TestCase
209
+ def test_success
210
+ assert_equal(123, T.check(T.union(str: String, int: Integer), 123))
211
+ end
212
+
213
+ def test_fail
214
+ assert_raise TypeError do
215
+ T.check(T.union(str: String, int: Integer), true)
216
+ end
217
+ end
218
+ end
219
+
185
220
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: emery
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vladimir Sapronov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-03-25 00:00:00.000000000 Z
11
+ date: 2020-03-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json