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 +4 -4
- data/lib/emery/jsoner.rb +25 -0
- data/lib/emery/type.rb +18 -7
- data/test/jsoner_test.rb +24 -3
- data/test/type_test.rb +35 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e7526be75b8c44c624947657c22214dd7715170e1bbdb8b46a8369a6ca66d4fc
|
4
|
+
data.tar.gz: 5483955dd2c563ca2c6c04662aea8bc1f9b4a5e34817b9d60a046afa32ca5a04
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
46
|
-
|
47
|
-
|
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
|
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
|
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
|
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.
|
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-
|
11
|
+
date: 2020-03-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: json
|