emery 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
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