divine 0.0.2 → 0.0.3
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.
- data/.gitignore +30 -0
- data/README.md +57 -0
- data/Rakefile +45 -18
- data/lib/divine.rb +3 -3
- data/lib/divine/code_generators/code_generator.rb +112 -14
- data/lib/divine/code_generators/java.rb +144 -80
- data/lib/divine/code_generators/javascript.rb +192 -104
- data/lib/divine/code_generators/ruby.rb +133 -60
- data/lib/divine/dsl.rb +70 -12
- data/lib/divine/version.rb +1 -1
- data/test/basic_complex_test/js_test/js_testBasic.js +1 -1
- data/test/basic_complex_test/js_test/js_testComplex.js +1 -1
- data/test/basic_complex_test/ruby_test/ruby_test.rb +10 -10
- data/test/binaryTree_test/js_test/js_test.js +1 -1
- data/test/binaryTree_test/ruby_test/ruby_test.rb +4 -4
- data/test/complex_test/js_test/js_test.js +3 -2
- data/test/ipv6_test/java_test/JavaTest.java +4 -6
- data/test/ipv6_test/js_test/js_test.js +1 -1
- data/test/signed_float_test/ruby_test/ruby_test.rb +36 -0
- data/test/signed_float_test/signed_float_test.rb +14 -0
- data/test/signed_int_test/java_test/JavaTest.java +83 -0
- data/test/signed_int_test/js_test/js_test.js +55 -0
- data/test/signed_int_test/ruby_test/ruby_test.rb +37 -0
- data/test/signed_int_test/signed_int_test.rb +15 -0
- data/test/unify_test/unify_test.rb +24 -13
- metadata +14 -38
- data/test/basic_complex_test/java_test/test_babel.java +0 -368
- data/test/basic_complex_test/js_test/test_babel.js +0 -523
- data/test/basic_complex_test/ruby_test/test_babel.rb +0 -368
- data/test/binaryTree_test/java_test/test_binaryTree.java +0 -301
- data/test/binaryTree_test/js_test/test_binaryTree.js +0 -447
- data/test/binaryTree_test/ruby_test/test_binaryTree.rb +0 -303
- data/test/complex_test/java_test/test_complex.java +0 -331
- data/test/complex_test/js_test/test_complex.js +0 -478
- data/test/complex_test/ruby_test/test_complex.rb +0 -330
- data/test/ipv6_test/java_test/junit.jar +0 -0
- data/test/ipv6_test/java_test/test_ipv6.java +0 -270
- data/test/ipv6_test/js_test/test_ipv6.js +0 -409
- data/test/ipv6_test/ruby_test/test_ipv6.rb +0 -267
- data/test/unify_test/java_test/test_unify.java +0 -171
- data/test/unify_test/js_test/js_test.js +0 -56
- data/test/unify_test/js_test/test_unify.js +0 -326
- data/test/unify_test/ruby_test/ruby_test.rb +0 -35
- data/test/unify_test/ruby_test/test_unify.rb +0 -187
@@ -1,6 +1,12 @@
|
|
1
1
|
module Divine
|
2
2
|
|
3
3
|
class RubyHelperMethods < BabelHelperMethods
|
4
|
+
def get_header_comment
|
5
|
+
get_header_comment_text.map do |s|
|
6
|
+
"# #{s}"
|
7
|
+
end.join("\n")
|
8
|
+
end
|
9
|
+
|
4
10
|
def ruby_base_class_template_str
|
5
11
|
%q{
|
6
12
|
class BabelBase<%= toplevel_class %>
|
@@ -29,6 +35,24 @@ module Divine
|
|
29
35
|
(data.getbyte << 24) | read_int24(data)
|
30
36
|
end
|
31
37
|
|
38
|
+
def read_sint32(data)
|
39
|
+
max = (2** (32 - 1)) - 1
|
40
|
+
num = (data.getbyte << 24) | read_int24(data)
|
41
|
+
if num > max
|
42
|
+
return num - 2** 32
|
43
|
+
end
|
44
|
+
return num
|
45
|
+
end
|
46
|
+
|
47
|
+
def read_sint64(data)
|
48
|
+
max = (2** (64 - 1)) - 1
|
49
|
+
num = (read_int32(data) << 32) | (read_int32(data) & 0xFFFFFFFF);
|
50
|
+
if num > max
|
51
|
+
return num - 2** 64
|
52
|
+
end
|
53
|
+
return num
|
54
|
+
end
|
55
|
+
|
32
56
|
def read_bool(data)
|
33
57
|
read_int8(data) == 1
|
34
58
|
end
|
@@ -107,6 +131,26 @@ module Divine
|
|
107
131
|
write_int24( v & 0xFFFFFF, out)
|
108
132
|
end
|
109
133
|
|
134
|
+
def write_sint32(v, out)
|
135
|
+
v = v.to_i
|
136
|
+
max = (2** (32 - 1)) - 1
|
137
|
+
min = (2** (32 - 1) ) - (2** 32)
|
138
|
+
raise_error "Too large Sint32 number: #{v} , Max = #{max}" if v > max # Max 2.147.483.647
|
139
|
+
raise_error "Too small sInt32 number: #{v} , Min = #{min}" if v < min # Min -2.147.483.648
|
140
|
+
write_int8( v >> 24 & 0xFF, out)
|
141
|
+
write_int24( v & 0xFFFFFF, out)
|
142
|
+
end
|
143
|
+
|
144
|
+
def write_sint64(v, out)
|
145
|
+
v = v.to_i
|
146
|
+
max = (2** (64 - 1)) - 1
|
147
|
+
min = (2** (64 - 1) ) - (2** 64)
|
148
|
+
raise_error "Too large Sint32 number: #{v} , Max = #{max}" if v > max # Max 2.147.483.647
|
149
|
+
raise_error "Too small sInt32 number: #{v} , Min = #{min}" if v < min # Min -2.147.483.648
|
150
|
+
write_int32( v >> 32 & 0xFFFFFFFF, out)
|
151
|
+
write_int32( v & 0xFFFFFFFF, out)
|
152
|
+
end
|
153
|
+
|
110
154
|
def write_bool(v, out)
|
111
155
|
write_int8(v ? 1 : 0, out)
|
112
156
|
end
|
@@ -236,50 +280,99 @@ module Divine
|
|
236
280
|
}
|
237
281
|
end
|
238
282
|
|
239
|
-
def
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
283
|
+
def ruby_class_template(sh)
|
284
|
+
code = [
|
285
|
+
"class #{sh.name} < BabelBase",
|
286
|
+
:indent,
|
287
|
+
"",
|
288
|
+
|
289
|
+
# PROPERTIES
|
290
|
+
if sh.field_names.size > 0
|
291
|
+
"attr_accessor :struct_version, #{sh.field_names.map {|n| ":#{n}" }.join(', ')}"
|
292
|
+
else
|
293
|
+
"attr_accessor :struct_version"
|
294
|
+
end, "",
|
295
|
+
|
296
|
+
|
297
|
+
# INITIALIZE
|
298
|
+
"def initialize()",
|
299
|
+
:indent,
|
300
|
+
"super",
|
301
|
+
"@struct_version ||= #{sh.latest_version}",
|
302
|
+
sh.field_names.map do |fn|
|
303
|
+
"@#{fn} ||= #{ruby_get_empty_declaration(sh.field(fn).first)}"
|
304
|
+
end,
|
305
|
+
:deindent,
|
306
|
+
"end", "",
|
307
|
+
|
308
|
+
# SERiALIZE INTERNAL
|
309
|
+
"def serialize_internal(out)",
|
310
|
+
:indent,
|
311
|
+
"write_int8(@struct_version, out)",
|
312
|
+
sh.structs.map do |s|
|
313
|
+
[
|
314
|
+
"if @struct_version == #{s.version}",
|
315
|
+
:indent,
|
316
|
+
s.simple_fields.map do |f|
|
317
|
+
"write_#{f.type}(#{f.name}, out)"
|
318
|
+
end,
|
319
|
+
s.complex_fields.map do |f|
|
320
|
+
[
|
321
|
+
"", "# Serialize #{f.type} '#{f.name}'",
|
322
|
+
ruby_serialize_internal(f.name, f.referenced_types)
|
323
|
+
]
|
324
|
+
end,
|
325
|
+
"return",
|
326
|
+
:deindent,
|
327
|
+
"end", ""
|
328
|
+
]
|
329
|
+
end, "",
|
330
|
+
"raise \"Unsupported version #\{@struct_version\} for type '#{sh.name}'\"",
|
331
|
+
:deindent,
|
332
|
+
"end", "",
|
333
|
+
|
334
|
+
# DESERIALIZE
|
335
|
+
"def deserialize(data)",
|
336
|
+
:indent,
|
337
|
+
"@struct_version = read_int8(data)",
|
338
|
+
sh.structs.map do |s|
|
339
|
+
[
|
340
|
+
"if @struct_version == #{s.version}",
|
341
|
+
:indent,
|
342
|
+
s.simple_fields.map do |f|
|
343
|
+
"@#{f.name} = read_#{f.type}(data)"
|
344
|
+
end,
|
345
|
+
s.complex_fields.map do |f|
|
346
|
+
[
|
347
|
+
"", "# Read #{f.type} '#{f.name}'",
|
348
|
+
ruby_deserialize_internal("@#{f.name}", f.referenced_types)
|
349
|
+
]
|
350
|
+
end,
|
351
|
+
"return",
|
352
|
+
:deindent,
|
353
|
+
"end"
|
354
|
+
]
|
355
|
+
end, "",
|
356
|
+
"raise \"Unsupported version #\{@struct_version\} for type '#{sh.name}'\"",
|
357
|
+
:deindent,
|
358
|
+
"end", "",
|
359
|
+
|
360
|
+
|
361
|
+
# END OF CLASS
|
362
|
+
:deindent,
|
363
|
+
"end"
|
364
|
+
]
|
365
|
+
format_src(0, 3, code)
|
274
366
|
end
|
275
367
|
|
368
|
+
|
276
369
|
def ruby_get_empty_declaration(field)
|
277
370
|
case field.type
|
278
371
|
when :list, :binary, :short_binary
|
279
372
|
"[]"
|
280
373
|
when :map
|
281
374
|
"{}"
|
282
|
-
when :int8, :int16, :int32
|
375
|
+
when :int8, :int16, :int32, :sint32, :sint64
|
283
376
|
"0"
|
284
377
|
when :string, :ip_number
|
285
378
|
"\"\""
|
@@ -288,15 +381,6 @@ module Divine
|
|
288
381
|
end
|
289
382
|
end
|
290
383
|
|
291
|
-
def ruby_serialize_complex(field)
|
292
|
-
types = field.referenced_types
|
293
|
-
as = [
|
294
|
-
"# Serialize #{field.type} '#{field.name}'",
|
295
|
-
ruby_serialize_internal(field.name, types)
|
296
|
-
]
|
297
|
-
format_src(6, 3, as)
|
298
|
-
end
|
299
|
-
|
300
384
|
def ruby_serialize_internal(var, types)
|
301
385
|
if types.respond_to? :first
|
302
386
|
case types.first
|
@@ -338,15 +422,6 @@ module Divine
|
|
338
422
|
end
|
339
423
|
end
|
340
424
|
|
341
|
-
def ruby_deserialize_complex(field)
|
342
|
-
types = field.referenced_types
|
343
|
-
as = [
|
344
|
-
"# Deserialize #{field.type} '#{field.name}'",
|
345
|
-
ruby_deserialize_internal("@#{field.name}", types)
|
346
|
-
]
|
347
|
-
format_src(6, 3, as)
|
348
|
-
end
|
349
|
-
|
350
425
|
def ruby_deserialize_internal(var, types)
|
351
426
|
if types.respond_to? :first
|
352
427
|
case types.first
|
@@ -406,21 +481,19 @@ module Divine
|
|
406
481
|
@debug = true
|
407
482
|
|
408
483
|
def generate_code(structs, opts)
|
409
|
-
pp opts
|
410
484
|
base_template = Erubis::Eruby.new(ruby_base_class_template_str)
|
411
|
-
class_template = Erubis::Eruby.new(ruby_class_template_str)
|
412
485
|
keys = structs.keys.sort
|
413
486
|
src = keys.map do |k|
|
414
487
|
ss = structs[k]
|
415
|
-
#
|
416
|
-
|
417
|
-
|
488
|
+
# Check different aspects the the structs
|
489
|
+
vss = sanity_check(ss)
|
490
|
+
ruby_class_template(StructHandler.new(vss))
|
418
491
|
end
|
419
492
|
|
420
493
|
# User defined super class?
|
421
494
|
toplevel = opts[:parent_class] || nil
|
422
495
|
toplevel = " < #{toplevel}" if toplevel
|
423
|
-
return [{file: opts[:file], src: "#{ruby_get_begin_module(opts)}#{base_template.result({ toplevel_class: toplevel })}\n\n#{src.join("\n\n")}#{ruby_get_end_module(opts)}"}]
|
496
|
+
return [{file: opts[:file], src: "#{get_header_comment}\n#{ruby_get_begin_module(opts)}#{base_template.result({ toplevel_class: toplevel, this: self })}\n\n#{src.join("\n\n")}#{ruby_get_end_module(opts)}"}]
|
424
497
|
end
|
425
498
|
|
426
499
|
def ruby_get_begin_module(opts)
|
data/lib/divine/dsl.rb
CHANGED
@@ -2,7 +2,8 @@ module Divine
|
|
2
2
|
$all_structs = {}
|
3
3
|
|
4
4
|
class StructDefinition
|
5
|
-
def initialize(type, args)
|
5
|
+
def initialize(owner, type, args)
|
6
|
+
@owner = owner
|
6
7
|
@type = type
|
7
8
|
@args = args
|
8
9
|
end
|
@@ -14,12 +15,20 @@ module Divine
|
|
14
15
|
def type
|
15
16
|
@type
|
16
17
|
end
|
18
|
+
|
19
|
+
def version
|
20
|
+
@owner.version
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_s
|
24
|
+
"#{@owner.name}: #{self.type} #{self.name} (#{self.class.name}, #{@args.inspect})"
|
25
|
+
end
|
17
26
|
end
|
18
27
|
|
19
28
|
class SimpleDefinition < StructDefinition
|
20
29
|
def simple?; true; end
|
21
30
|
def referenced_types
|
22
|
-
@type
|
31
|
+
[@type]
|
23
32
|
end
|
24
33
|
end
|
25
34
|
|
@@ -39,6 +48,12 @@ module Divine
|
|
39
48
|
end
|
40
49
|
end
|
41
50
|
|
51
|
+
class SInteger64Definition < SimpleDefinition
|
52
|
+
end
|
53
|
+
|
54
|
+
class SInteger32Definition < SimpleDefinition
|
55
|
+
end
|
56
|
+
|
42
57
|
class Integer32Definition < SimpleDefinition
|
43
58
|
end
|
44
59
|
|
@@ -84,6 +99,8 @@ module Divine
|
|
84
99
|
|
85
100
|
|
86
101
|
$available_types = {
|
102
|
+
sint64: SInteger64Definition,
|
103
|
+
sint32: SInteger32Definition,
|
87
104
|
int32: Integer32Definition,
|
88
105
|
int24: Integer24Definition,
|
89
106
|
int16: Integer16Definition,
|
@@ -102,10 +119,10 @@ module Divine
|
|
102
119
|
# Name = name of the struct
|
103
120
|
# Version = struct version (not currently used)
|
104
121
|
# Fields = All defined fields
|
105
|
-
attr_reader :name, :
|
122
|
+
attr_reader :name, :properties, :fields
|
106
123
|
|
107
|
-
def initialize(name,
|
108
|
-
@
|
124
|
+
def initialize(name, ps)
|
125
|
+
@properties = ps
|
109
126
|
@name = name.to_sym
|
110
127
|
@fields = []
|
111
128
|
unless @name == :_inline_
|
@@ -114,35 +131,76 @@ module Divine
|
|
114
131
|
end
|
115
132
|
end
|
116
133
|
|
134
|
+
#
|
135
|
+
# Get the version of the struct
|
136
|
+
#
|
137
|
+
def version
|
138
|
+
if properties && properties[:version]
|
139
|
+
properties[:version].to_i
|
140
|
+
else
|
141
|
+
1
|
142
|
+
end
|
143
|
+
rescue => e
|
144
|
+
raise "Failed to get version number from '#{name}': #{properties.inspect}\n#{e}"
|
145
|
+
end
|
146
|
+
|
147
|
+
#
|
148
|
+
# Is the struct freezed? I.e. no changes are allowed
|
149
|
+
#
|
150
|
+
def freezed?
|
151
|
+
nil != freeze_signature
|
152
|
+
end
|
153
|
+
|
154
|
+
#
|
155
|
+
# Get the freeze signature
|
156
|
+
#
|
157
|
+
def freeze_signature
|
158
|
+
if properties && properties[:freeze]
|
159
|
+
properties[:freeze]
|
160
|
+
else
|
161
|
+
nil
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
117
165
|
#
|
118
166
|
# Get all simple fields, i.e. basic types like string, etc
|
119
167
|
#
|
120
168
|
def simple_fields
|
121
|
-
|
169
|
+
fields.select(&:simple?)
|
122
170
|
end
|
123
171
|
|
124
172
|
#
|
125
173
|
# Get all complex fields, i.e. lists and hashmaps
|
126
174
|
#
|
127
175
|
def complex_fields
|
128
|
-
|
176
|
+
fields.reject(&:simple?)
|
177
|
+
end
|
178
|
+
|
179
|
+
#
|
180
|
+
# Get named field
|
181
|
+
#
|
182
|
+
def get_field(name)
|
183
|
+
fields.each do |f|
|
184
|
+
return f if f.name == name
|
185
|
+
end
|
186
|
+
return nil
|
129
187
|
end
|
130
188
|
|
131
189
|
def method_missing(m, *args, &block)
|
132
|
-
puts "... #{m}"
|
190
|
+
#puts "... #{m} #{args.inspect}"
|
133
191
|
type = $available_types[m]
|
134
192
|
if type
|
135
193
|
if block_given?
|
136
|
-
puts ".... recursive definition"
|
137
|
-
builder = StructBuilder.new(:_inline_,
|
194
|
+
#puts ".... recursive definition"
|
195
|
+
builder = StructBuilder.new(:_inline_, args)
|
138
196
|
Docile.dsl_eval(builder, &block)
|
139
197
|
args << builder
|
140
198
|
end
|
141
199
|
if @name == :_inline_
|
142
200
|
# Pad the _inline_ name to anonymous inner types
|
143
|
-
@fields << type.new(m, [@name] + args)
|
201
|
+
@fields << type.new(self, m, [@name] + args)
|
144
202
|
else
|
145
|
-
@fields << type.new(m, args)
|
203
|
+
@fields << type.new(self, m, args)
|
146
204
|
end
|
147
205
|
#puts "... adding #{m} to #{name}, got #{fields} ..."
|
148
206
|
else
|
data/lib/divine/version.rb
CHANGED
@@ -18,7 +18,7 @@ var read = deserialize();
|
|
18
18
|
|
19
19
|
|
20
20
|
var testBasic_deser = new TestBasic();
|
21
|
-
testBasic_deser.deserialize(new
|
21
|
+
testBasic_deser.deserialize(new DivineDataReader(read));
|
22
22
|
|
23
23
|
assert.equal(testBasic_ser.i8, testBasic_deser.i8);
|
24
24
|
assert.equal(testBasic_ser.i16, testBasic_deser.i16);
|
@@ -16,7 +16,7 @@ serialize(ca);
|
|
16
16
|
var read = deserialize();
|
17
17
|
|
18
18
|
var testComplex_deser = new TestComplex();
|
19
|
-
testComplex_deser.deserialize(new
|
19
|
+
testComplex_deser.deserialize(new DivineDataReader(read));
|
20
20
|
|
21
21
|
compare_list(testComplex_ser.list1, testComplex_deser.list1);
|
22
22
|
compare_list(testComplex_ser.list2, testComplex_deser.list2);
|
@@ -24,12 +24,12 @@ class TestBabelTestBasic < MiniTest::Unit::TestCase
|
|
24
24
|
testbasic_deser = BabelTest::TestBasic.new
|
25
25
|
testbasic_deser.deserialize res
|
26
26
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
27
|
+
assert_equal testbasic_ser.i8 , testbasic_deser.i8
|
28
|
+
assert_equal testbasic_ser.i16 , testbasic_deser.i16
|
29
|
+
assert_equal testbasic_ser.i32 , testbasic_deser.i32
|
30
|
+
assert_equal testbasic_ser.str , testbasic_deser.str
|
31
|
+
assert_equal testbasic_ser.ip , testbasic_deser.ip
|
32
|
+
assert_equal testbasic_ser.guid , testbasic_deser.guid
|
33
33
|
end
|
34
34
|
|
35
35
|
def test_complex
|
@@ -48,11 +48,11 @@ class TestBabelTestBasic < MiniTest::Unit::TestCase
|
|
48
48
|
testcomplex_deser = BabelTest::TestComplex.new
|
49
49
|
testcomplex_deser.deserialize res
|
50
50
|
|
51
|
-
|
52
|
-
|
53
|
-
|
51
|
+
assert_equal testcomplex_ser.list1, testcomplex_deser.list1
|
52
|
+
assert_equal testcomplex_ser.list2, testcomplex_deser.list2
|
53
|
+
assert_equal testcomplex_ser.map1, testcomplex_deser.map1
|
54
54
|
testcomplex_ser.map2.keys.each do |k|
|
55
|
-
|
55
|
+
assert_equal testcomplex_ser.map2[k].length, testcomplex_deser.map2[k].length
|
56
56
|
end
|
57
57
|
end
|
58
58
|
|