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.
Files changed (44) hide show
  1. data/.gitignore +30 -0
  2. data/README.md +57 -0
  3. data/Rakefile +45 -18
  4. data/lib/divine.rb +3 -3
  5. data/lib/divine/code_generators/code_generator.rb +112 -14
  6. data/lib/divine/code_generators/java.rb +144 -80
  7. data/lib/divine/code_generators/javascript.rb +192 -104
  8. data/lib/divine/code_generators/ruby.rb +133 -60
  9. data/lib/divine/dsl.rb +70 -12
  10. data/lib/divine/version.rb +1 -1
  11. data/test/basic_complex_test/js_test/js_testBasic.js +1 -1
  12. data/test/basic_complex_test/js_test/js_testComplex.js +1 -1
  13. data/test/basic_complex_test/ruby_test/ruby_test.rb +10 -10
  14. data/test/binaryTree_test/js_test/js_test.js +1 -1
  15. data/test/binaryTree_test/ruby_test/ruby_test.rb +4 -4
  16. data/test/complex_test/js_test/js_test.js +3 -2
  17. data/test/ipv6_test/java_test/JavaTest.java +4 -6
  18. data/test/ipv6_test/js_test/js_test.js +1 -1
  19. data/test/signed_float_test/ruby_test/ruby_test.rb +36 -0
  20. data/test/signed_float_test/signed_float_test.rb +14 -0
  21. data/test/signed_int_test/java_test/JavaTest.java +83 -0
  22. data/test/signed_int_test/js_test/js_test.js +55 -0
  23. data/test/signed_int_test/ruby_test/ruby_test.rb +37 -0
  24. data/test/signed_int_test/signed_int_test.rb +15 -0
  25. data/test/unify_test/unify_test.rb +24 -13
  26. metadata +14 -38
  27. data/test/basic_complex_test/java_test/test_babel.java +0 -368
  28. data/test/basic_complex_test/js_test/test_babel.js +0 -523
  29. data/test/basic_complex_test/ruby_test/test_babel.rb +0 -368
  30. data/test/binaryTree_test/java_test/test_binaryTree.java +0 -301
  31. data/test/binaryTree_test/js_test/test_binaryTree.js +0 -447
  32. data/test/binaryTree_test/ruby_test/test_binaryTree.rb +0 -303
  33. data/test/complex_test/java_test/test_complex.java +0 -331
  34. data/test/complex_test/js_test/test_complex.js +0 -478
  35. data/test/complex_test/ruby_test/test_complex.rb +0 -330
  36. data/test/ipv6_test/java_test/junit.jar +0 -0
  37. data/test/ipv6_test/java_test/test_ipv6.java +0 -270
  38. data/test/ipv6_test/js_test/test_ipv6.js +0 -409
  39. data/test/ipv6_test/ruby_test/test_ipv6.rb +0 -267
  40. data/test/unify_test/java_test/test_unify.java +0 -171
  41. data/test/unify_test/js_test/js_test.js +0 -56
  42. data/test/unify_test/js_test/test_unify.js +0 -326
  43. data/test/unify_test/ruby_test/ruby_test.rb +0 -35
  44. 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 ruby_class_template_str
240
- %q{
241
- class <%= c.name %> < BabelBase
242
- <% unless c.fields.empty? %>
243
- attr_accessor <%= c.fields.map { |x| ":#{x.name}" }.join(', ') %>
244
-
245
- def initialize()
246
- super
247
- <% c.fields.each do |f| %>
248
- @<%= f.name %> ||= <%= this.ruby_get_empty_declaration(f) %>
249
- <% end %>
250
- end
251
- <% end %>
252
-
253
- def serialize_internal(out)
254
- print "+"
255
- <% c.simple_fields.each do |f| %>
256
- write_<%= f.type %>(<%= f.name %>, out)
257
- <% end %>
258
- <% c.complex_fields.each do |f| %>
259
- <%= this.ruby_serialize_complex f %>
260
- <% end %>
261
- end
262
-
263
- def deserialize(data)
264
- print "-"
265
- <% c.simple_fields.each do |f| %>
266
- @<%= f.name %> = read_<%= f.type %>(data)
267
- <% end %>
268
- <% c.complex_fields.each do |f| %>
269
- <%= this.ruby_deserialize_complex f %>
270
- <% end %>
271
- end
272
- end
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
- # TODO: Should we merge different versions and deduce deprecated methods, warn for incompatible changes, etc?
416
- raise "Duplicate definitions of struct #{k}" if ss.size > 1
417
- class_template.result( c: ss.first, this: self )
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)
@@ -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, :version, :fields
122
+ attr_reader :name, :properties, :fields
106
123
 
107
- def initialize(name, version)
108
- @version = version
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
- fields.select(&:simple?)
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
- fields.reject(&:simple?)
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_, version)
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
@@ -1,3 +1,3 @@
1
1
  module Divine
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
@@ -18,7 +18,7 @@ var read = deserialize();
18
18
 
19
19
 
20
20
  var testBasic_deser = new TestBasic();
21
- testBasic_deser.deserialize(new BabelDataReader(read));
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 BabelDataReader(read));
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
- assert testbasic_ser.i8 == testbasic_deser.i8
28
- assert testbasic_ser.i16 == testbasic_deser.i16
29
- assert testbasic_ser.i32 == testbasic_deser.i32
30
- assert testbasic_ser.str == testbasic_deser.str
31
- assert testbasic_ser.ip == testbasic_deser.ip
32
- assert testbasic_ser.guid == testbasic_deser.guid
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
- assert testcomplex_ser.list1.sort == testcomplex_deser.list1.sort
52
- assert testcomplex_ser.list2.sort == testcomplex_deser.list2.sort
53
- assert testcomplex_ser.map1 == testcomplex_deser.map1
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
- assert testcomplex_ser.map2[k].length == testcomplex_deser.map2[k].length
55
+ assert_equal testcomplex_ser.map2[k].length, testcomplex_deser.map2[k].length
56
56
  end
57
57
  end
58
58