xdrgen 0.1.0 → 0.1.1

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: 30ccfde98b0baa13f03916b4b2d89c774ed8119e373e23541ca8e46e87f1db06
4
- data.tar.gz: abd5834683ef1d6e74e6decf61b7c3155a0cf1ef5fd03a4592acb43abd2e7446
3
+ metadata.gz: 838bb9438d35d145a409589e774549bf2e74ef83c25156abf40f410e2064a32b
4
+ data.tar.gz: 25488d84cb7c5c641c52308e915d8b2d4d63631c67aa7bcda22c18635fb0fd7b
5
5
  SHA512:
6
- metadata.gz: '040408ad8434aaa992df6533dd66954c85c389cfe76130ca188c2008c1592a758e315c0036929e9064b48d3d49bcf18fdf902455f1a7fdd0522da91d76d6085e'
7
- data.tar.gz: ec2721ba15cb25ec6aff042a5c1c3697b557d1dab85e6c61a2cc242b5be87c6af815e1e685b335e21e7da98b0ebe4156cc39444057141e8fb8521231b2444d7e
6
+ metadata.gz: 5bb40e6312ffc8c27febe50c367ab0b99141751b0b1b47c4a51c3cff7d33420b8a1410318175657756dbefc4ed20d7e9de5f37415692f423cd7043476e45842a
7
+ data.tar.gz: 33d7132dad38f3baedf34e17acc5704c688fdd280908864732f607821e831d6eca7e6544d258a80ff1575e547e50b38985131ed54d6a7286b05777942c2e729b
@@ -0,0 +1,23 @@
1
+ name: Ruby
2
+
3
+ on:
4
+ push:
5
+ branches: [ master ]
6
+ pull_request:
7
+
8
+ jobs:
9
+ test:
10
+ runs-on: ubuntu-latest
11
+ strategy:
12
+ matrix:
13
+ ruby-version: ['2.7', '3.0']
14
+
15
+ steps:
16
+ - uses: actions/checkout@v2
17
+ - name: Set up Ruby
18
+ uses: ruby/setup-ruby@473e4d8fe5dd94ee328fdfca9f8c9c7afc9dae5e
19
+ with:
20
+ ruby-version: ${{ matrix.ruby-version }}
21
+ bundler-cache: true # runs 'bundle install' and caches installed gems automatically
22
+ - name: Run Rspec tests
23
+ run: bundle exec rspec
data/README.md CHANGED
@@ -25,7 +25,8 @@ golang, and elixir:
25
25
  - golang: currently using a fork of go-xdr, but has complete support
26
26
  - elixir: support is experimental as the SDK is in early development. Generated
27
27
  code requires [:exdr](https://github.com/revelrylabs/exdr) in your deps
28
-
28
+ - C#: complete support
29
+
29
30
  Testing is _very_ sparse, but will improve over time.
30
31
 
31
32
  ## Usage as a binary
data/lib/xdrgen/cli.rb CHANGED
@@ -5,7 +5,7 @@ module Xdrgen
5
5
  def self.run(args)
6
6
  args = args.dup
7
7
  opts = Slop.parse! args do
8
- banner 'Usage: xdrgen -o OUTPUT_DIR INPUT --gen=ruby'
8
+ banner 'Usage: xdrgen -o OUTPUT_DIR INPUT --language=ruby'
9
9
  on 'o', 'output=', 'The output directory'
10
10
  on 'l', 'language=', 'The output language', default: 'ruby'
11
11
  on 'n', 'namespace=', '"namespace" to generate code within (language-specific)'
@@ -16,7 +16,7 @@ module Xdrgen
16
16
 
17
17
  compilation = Compilation.new(
18
18
  args,
19
- output_dir: opts[:output],
19
+ output_dir: opts[:output],
20
20
  language: opts[:language].to_sym,
21
21
  namespace: opts[:namespace]
22
22
  )
@@ -28,4 +28,4 @@ module Xdrgen
28
28
  exit(code)
29
29
  end
30
30
  end
31
- end
31
+ end
@@ -7,6 +7,7 @@ module Xdrgen::Generators
7
7
  autoload :Javascript
8
8
  autoload :Java
9
9
  autoload :Elixir
10
+ autoload :Csharp
10
11
 
11
12
  def self.for_language(language)
12
13
  const_get language.to_s.classify
@@ -0,0 +1,580 @@
1
+ module Xdrgen
2
+ module Generators
3
+ class Csharp < Xdrgen::Generators::Base
4
+ def generate
5
+ render_lib
6
+ render_definitions(@top)
7
+ end
8
+
9
+ def render_lib; end
10
+
11
+ def render_definitions(node)
12
+ node.namespaces.each { |n| render_definitions n }
13
+ node.definitions.each(&method(:render_definition))
14
+ end
15
+
16
+ def render_definition(defn)
17
+ case defn
18
+ when AST::Definitions::Struct
19
+ render_element 'public class', defn do |out|
20
+ render_struct defn, out
21
+ render_nested_definitions defn, out
22
+ end
23
+ when AST::Definitions::Enum
24
+ render_element 'public class', defn do |out|
25
+ render_enum defn, out
26
+ end
27
+ when AST::Definitions::Union
28
+ render_element 'public class', defn do |out|
29
+ render_union defn, out
30
+ render_nested_definitions defn, out
31
+ end
32
+ when AST::Definitions::Typedef
33
+ render_element 'public class', defn do |out|
34
+ render_typedef defn, out
35
+ end
36
+ end
37
+ end
38
+
39
+ def render_nested_definitions(defn, out)
40
+ return unless defn.respond_to? :nested_definitions
41
+ defn.nested_definitions.each do |ndefn|
42
+ case ndefn
43
+ when AST::Definitions::Struct
44
+ name = name ndefn
45
+ out.puts "public class #{name} {"
46
+ out.indent do
47
+ render_struct ndefn, out
48
+ render_nested_definitions ndefn, out
49
+ end
50
+ out.puts '}'
51
+ when AST::Definitions::Enum
52
+ name = name ndefn
53
+ out.puts "public class #{name} {"
54
+ out.indent do
55
+ render_enum ndefn, out
56
+ end
57
+ out.puts '}'
58
+ when AST::Definitions::Union
59
+ name = name ndefn
60
+ out.puts "public class #{name} {"
61
+ out.indent do
62
+ render_union ndefn, out
63
+ render_nested_definitions ndefn, out
64
+ end
65
+ out.puts '}'
66
+ when AST::Definitions::Typedef
67
+ name = name ndefn
68
+ out.puts "public class #{name} {"
69
+ out.indent do
70
+ render_typedef ndefn, out
71
+ end
72
+ out.puts '}'
73
+ end
74
+ end
75
+ end
76
+
77
+ def render_element(type, element, post_name = '')
78
+ path = element.name.camelize + '.cs'
79
+ name = name_string element.name
80
+ out = @output.open(path)
81
+ render_top_matter out
82
+ render_source_comment out, element
83
+
84
+ out.puts "#{type} #{name} #{post_name} {"
85
+ out.indent do
86
+ yield out
87
+ out.unbreak
88
+ end
89
+ out.puts '}'
90
+ out.puts '}'
91
+ end
92
+
93
+ def render_enum(enum, out)
94
+ enumname = enum.name + 'Enum'
95
+
96
+ out.puts "public enum #{enumname} {"
97
+ out.balance_after /,[\s]*/ do
98
+ enum.members.each do |em|
99
+ out.puts "#{em.name} = #{em.value},"
100
+ end
101
+ end
102
+ out.puts "}\n"
103
+ out.puts <<-EOS.strip_heredoc
104
+ public #{enumname} InnerValue {get; set;} = default(#{enumname});
105
+
106
+ public static #{enum.name} Create(#{enumname} v)
107
+ {
108
+ return new #{enum.name} {
109
+ InnerValue = v
110
+ };
111
+ }
112
+
113
+ public static #{name_string enum.name} Decode(XdrDataInputStream stream) {
114
+ int value = stream.ReadInt();
115
+ switch (value) {
116
+ EOS
117
+ out.indent 2 do
118
+ enum.members.each do |em|
119
+ out.puts "case #{em.value}: return Create(#{enumname}.#{em.name});"
120
+ end
121
+ end
122
+ out.puts <<-EOS.strip_heredoc
123
+ default:
124
+ throw new Exception("Unknown enum value: " + value);
125
+ }
126
+ }
127
+
128
+ public static void Encode(XdrDataOutputStream stream, #{name_string enum.name} value) {
129
+ stream.WriteInt((int)value.InnerValue);
130
+ }
131
+ EOS
132
+ out.break
133
+ end
134
+
135
+ def render_struct(struct, out)
136
+ out.puts "public #{name struct} () {}"
137
+ struct.members.each do |m|
138
+ out.puts <<-EOS.strip_heredoc
139
+ public #{decl_string(m.declaration)} #{m.name.camelize} {get; set;}
140
+ EOS
141
+ end
142
+ out.puts "\n"
143
+ out.puts "public static void Encode(XdrDataOutputStream stream, #{name struct} encoded#{name struct}) {"
144
+ struct.members.each do |m|
145
+ out.indent do
146
+ encode_member "encoded#{name struct}", m, out
147
+ end
148
+ end
149
+ out.puts '}'
150
+
151
+ out.puts <<-EOS.strip_heredoc
152
+ public static #{name struct} Decode(XdrDataInputStream stream) {
153
+ #{name struct} decoded#{name struct} = new #{name struct}();
154
+ EOS
155
+ struct.members.each do |m|
156
+ out.indent do
157
+ decode_member "decoded#{name struct}", m, out
158
+ end
159
+ end
160
+ out.indent do
161
+ out.puts "return decoded#{name struct};"
162
+ end
163
+ out.puts '}'
164
+
165
+ out.break
166
+ end
167
+
168
+ def render_typedef(typedef, out)
169
+ out.puts <<-EOS.strip_heredoc
170
+ public #{decl_string typedef.declaration} InnerValue {get; set;} = default(#{decl_string typedef.declaration});
171
+
172
+ public #{typedef.name.camelize}() {}
173
+
174
+ public #{typedef.name.camelize}(#{decl_string typedef.declaration} value)
175
+ {
176
+ InnerValue = value;
177
+ }
178
+
179
+ EOS
180
+ out.puts "public static void Encode(XdrDataOutputStream stream, #{name typedef} encoded#{name typedef}) {"
181
+ encode_innervalue_member "encoded#{name typedef}", typedef, out
182
+ out.puts '}'
183
+
184
+ out.puts <<-EOS.strip_heredoc
185
+ public static #{name typedef} Decode(XdrDataInputStream stream) {
186
+ #{name typedef} decoded#{name typedef} = new #{name typedef}();
187
+ EOS
188
+ decode_innervalue_member "decoded#{name typedef}", typedef, out
189
+ out.indent do
190
+ out.puts "return decoded#{name typedef};"
191
+ end
192
+ out.puts '}'
193
+ end
194
+
195
+ def render_union(union, out)
196
+ has_inner_value = false
197
+
198
+ out.puts "public #{name union} () {}"
199
+ out.puts <<-EOS.strip_heredoc
200
+
201
+ public #{type_string union.discriminant.type} Discriminant { get; set; } = new #{type_string union.discriminant.type}();
202
+
203
+ EOS
204
+ union.arms.each do |arm|
205
+ next if arm.void?
206
+ out.puts <<-EOS.strip_heredoc
207
+ public #{decl_string(arm.declaration)} #{arm.name.camelize} {get; set;}
208
+ EOS
209
+ end
210
+
211
+ out.puts "public static void Encode(XdrDataOutputStream stream, #{name union} encoded#{name union}) {"
212
+ if union.discriminant.type.is_a?(AST::Typespecs::Int)
213
+ out.puts "stream.WriteInt((int)encoded#{name union}.Discriminant);"
214
+ out.puts "switch (encoded#{name union}.Discriminant) {"
215
+ # elsif [discriminant is AST::Definitions::Typedef]
216
+ # out.puts "stream.writeInt(encoded#{name union}.getDiscriminant().get#{name union.discriminant.type}());"
217
+ else
218
+ has_inner_value = true
219
+ out.puts "stream.WriteInt((int)encoded#{name union}.Discriminant.InnerValue);"
220
+ out.puts "switch (encoded#{name union}.Discriminant.InnerValue) {"
221
+ end
222
+
223
+ union.arms.each do |arm|
224
+ case arm
225
+ when AST::Definitions::UnionDefaultArm
226
+ out.puts 'default:'
227
+ else
228
+ arm.cases.each do |kase|
229
+ if kase.value.is_a?(AST::Identifier)
230
+ out.puts "case #{type_string union.discriminant.type}.#{type_string union.discriminant.type}Enum.#{kase.value.name}:"
231
+ else
232
+ out.puts "case #{kase.value.value}:"
233
+ end
234
+ end
235
+ end
236
+ encode_member "encoded#{name union}", arm, out
237
+ out.puts 'break;'
238
+ end
239
+ out.puts "}\n}"
240
+
241
+ out.puts "public static #{name union} Decode(XdrDataInputStream stream) {"
242
+ out.puts "#{name union} decoded#{name union} = new #{name union}();"
243
+ if union.discriminant.type.is_a?(AST::Typespecs::Int)
244
+ out.puts 'int discriminant = stream.ReadInt();'
245
+ out.puts "decoded#{name union}.Discriminant = discriminant;"
246
+ out.puts "switch (decoded#{name union}.Discriminant) {"
247
+ else
248
+ out.puts "#{name union.discriminant.type} discriminant = #{name union.discriminant.type}.Decode(stream);"
249
+ out.puts "decoded#{name union}.Discriminant = discriminant;"
250
+ out.puts "switch (decoded#{name union}.Discriminant.InnerValue) {"
251
+ end
252
+
253
+ union.arms.each do |arm|
254
+ case arm
255
+ when AST::Definitions::UnionDefaultArm
256
+ out.puts 'default:'
257
+ else
258
+ arm.cases.each do |kase|
259
+ if kase.value.is_a?(AST::Identifier)
260
+ out.puts "case #{type_string union.discriminant.type}.#{type_string union.discriminant.type}Enum.#{kase.value.name}:"
261
+ else
262
+ out.puts "case #{kase.value.value}:"
263
+ end
264
+ end
265
+ end
266
+ decode_member "decoded#{name union}", arm, out
267
+ out.puts 'break;'
268
+ end
269
+ out.puts "}\n"
270
+ out.indent do
271
+ out.puts "return decoded#{name union};"
272
+ end
273
+ out.puts '}'
274
+
275
+ out.break
276
+ end
277
+
278
+ def render_top_matter(out)
279
+ out.puts <<-EOS.strip_heredoc
280
+ // Automatically generated by xdrgen
281
+ // DO NOT EDIT or your changes may be overwritten
282
+ using System;
283
+
284
+ namespace #{@namespace} {
285
+ EOS
286
+ out.break
287
+ end
288
+
289
+ def render_source_comment(out, defn)
290
+ return if defn.is_a?(AST::Definitions::Namespace)
291
+
292
+ out.puts <<-EOS.strip_heredoc
293
+ // === xdr source ============================================================
294
+
295
+ EOS
296
+
297
+ out.puts '// ' + defn.text_value.split("\n").join("\n// ")
298
+
299
+ out.puts <<-EOS.strip_heredoc
300
+
301
+ // ===========================================================================
302
+ EOS
303
+ end
304
+
305
+ def encode_innervalue_member(value, member, out)
306
+ case member.declaration
307
+ when AST::Declarations::Void
308
+ return
309
+ end
310
+
311
+ if member.type.sub_type == :optional
312
+ out.puts "if (#{value}.InnerValue != null) {"
313
+ out.puts 'stream.WriteInt(1);'
314
+ end
315
+
316
+ case member.declaration
317
+ when AST::Declarations::Opaque
318
+ out.puts "int #{member.name}size = #{value}.InnerValue.Length;"
319
+ unless member.declaration.fixed?
320
+ out.puts "stream.WriteInt(#{member.name.camelize}size);"
321
+ end
322
+ out.puts <<-EOS.strip_heredoc
323
+ stream.Write(#{value}.InnerValue, 0, #{member.name}size);
324
+ EOS
325
+ when AST::Declarations::Array
326
+ out.puts "int #{member.name}size = #{value}.InnerValue.Length;"
327
+ unless member.declaration.fixed?
328
+ out.puts "stream.WriteInt(#{member.name}size);"
329
+ end
330
+ out.puts <<-EOS.strip_heredoc
331
+ for (int i = 0; i < #{member.name}size; i++) {
332
+ #{encode_type member.declaration.type, "#{value}.InnerValue[i]"};
333
+ }
334
+ EOS
335
+ else
336
+ out.puts "#{encode_type member.declaration.type, "#{value}.InnerValue"};"
337
+ end
338
+ if member.type.sub_type == :optional
339
+ out.puts '} else {'
340
+ out.puts 'stream.WriteInt(0);'
341
+ out.puts '}'
342
+ end
343
+ end
344
+
345
+ def encode_member(value, member, out)
346
+ case member.declaration
347
+ when AST::Declarations::Void
348
+ return
349
+ end
350
+
351
+ if member.type.sub_type == :optional
352
+ out.puts "if (#{value}.#{member.name.camelize} != null) {"
353
+ out.puts 'stream.WriteInt(1);'
354
+ end
355
+ case member.declaration
356
+ when AST::Declarations::Opaque
357
+ out.puts "int #{member.name}size = #{value}.#{member.name.camelize}.Length;"
358
+ unless member.declaration.fixed?
359
+ out.puts "stream.WriteInt(#{member.name.camelize}size);"
360
+ end
361
+ out.puts <<-EOS.strip_heredoc
362
+ stream.Write(#{value}.#{member.name.camelize}, 0, #{member.name}size);
363
+ EOS
364
+ when AST::Declarations::Array
365
+ out.puts "int #{member.name}size = #{value}.#{member.name.camelize}.Length;"
366
+ unless member.declaration.fixed?
367
+ out.puts "stream.WriteInt(#{member.name}size);"
368
+ end
369
+ out.puts <<-EOS.strip_heredoc
370
+ for (int i = 0; i < #{member.name}size; i++) {
371
+ #{encode_type member.declaration.type, "#{value}.#{member.name.camelize}[i]"};
372
+ }
373
+ EOS
374
+ else
375
+ out.puts "#{encode_type member.declaration.type, "#{value}.#{member.name.camelize}"};"
376
+ end
377
+ if member.type.sub_type == :optional
378
+ out.puts '} else {'
379
+ out.puts 'stream.WriteInt(0);'
380
+ out.puts '}'
381
+ end
382
+ end
383
+
384
+ def encode_type(type, value)
385
+ case type
386
+ when AST::Typespecs::Int
387
+ "stream.WriteInt(#{value})"
388
+ when AST::Typespecs::UnsignedInt
389
+ "stream.WriteInt(#{value})"
390
+ when AST::Typespecs::Hyper
391
+ "stream.WriteLong(#{value})"
392
+ when AST::Typespecs::UnsignedHyper
393
+ "stream.WriteLong(#{value})"
394
+ when AST::Typespecs::Float
395
+ "stream.WriteFloat(#{value})"
396
+ when AST::Typespecs::Double
397
+ "stream.WriteDouble(#{value})"
398
+ when AST::Typespecs::Quadruple
399
+ raise 'cannot render quadruple in c#'
400
+ when AST::Typespecs::Bool
401
+ "stream.WriteInt(#{value} ? 1 : 0)"
402
+ when AST::Typespecs::String
403
+ "stream.WriteString(#{value})"
404
+ when AST::Typespecs::Simple
405
+ "#{name type.resolved_type}.Encode(stream, #{value})"
406
+ when AST::Concerns::NestedDefinition
407
+ "#{name type}.Encode(stream, #{value})"
408
+ else
409
+ raise "Unknown typespec: #{type.class.name}"
410
+ end
411
+ end
412
+
413
+ def decode_innervalue_member(value, member, out)
414
+ case member.declaration
415
+ when AST::Declarations::Void
416
+ return
417
+ end
418
+ if member.type.sub_type == :optional
419
+ out.puts <<-EOS.strip_heredoc
420
+ int #{member.name.camelize}Present = stream.ReadInt();
421
+ if (#{member.name.camelize}Present != 0) {
422
+ EOS
423
+ end
424
+ case member.declaration
425
+ when AST::Declarations::Opaque
426
+ if member.declaration.fixed?
427
+ out.puts "int #{member.name}size = #{member.declaration.size};"
428
+ else
429
+ out.puts "int #{member.name}size = stream.ReadInt();"
430
+ end
431
+ out.puts <<-EOS.strip_heredoc
432
+ #{value}.InnerValue = new byte[#{member.name}size];
433
+ stream.Read(#{value}.InnerValue, 0, #{member.name}size);
434
+ EOS
435
+ when AST::Declarations::Array
436
+ if member.declaration.fixed?
437
+ out.puts "int #{member.name}size = #{member.declaration.size};"
438
+ else
439
+ out.puts "int #{member.name}size = stream.ReadInt();"
440
+ end
441
+ out.puts <<-EOS.strip_heredoc
442
+ #{value}.InnerValue = new #{type_string member.type}[#{member.name}size];
443
+ for (int i = 0; i < #{member.name}size; i++) {
444
+ #{value}.InnerValue[i] = #{decode_type member.declaration.type};
445
+ }
446
+ EOS
447
+ else
448
+ out.puts "#{value}.InnerValue = #{decode_type member.declaration.type};"
449
+ end
450
+ out.puts '}' if member.type.sub_type == :optional
451
+ end
452
+
453
+ def decode_member(value, member, out)
454
+ case member.declaration
455
+ when AST::Declarations::Void
456
+ return
457
+ end
458
+ if member.type.sub_type == :optional
459
+ out.puts <<-EOS.strip_heredoc
460
+ int #{member.name.camelize}Present = stream.ReadInt();
461
+ if (#{member.name.camelize}Present != 0) {
462
+ EOS
463
+ end
464
+ case member.declaration
465
+ when AST::Declarations::Opaque
466
+ if member.declaration.fixed?
467
+ out.puts "int #{member.name}size = #{member.declaration.size};"
468
+ else
469
+ out.puts "int #{member.name}size = stream.ReadInt();"
470
+ end
471
+ out.puts <<-EOS.strip_heredoc
472
+ #{value}.#{member.name.camelize} = new byte[#{member.name}size];
473
+ stream.Read(#{value}.#{member.name.camelize},0,#{member.name}size);
474
+ EOS
475
+ when AST::Declarations::Array
476
+ if member.declaration.fixed?
477
+ out.puts "int #{member.name}size = #{member.declaration.size};"
478
+ else
479
+ out.puts "int #{member.name}size = stream.ReadInt();"
480
+ end
481
+ out.puts <<-EOS.strip_heredoc
482
+ #{value}.#{member.name.camelize} = new #{type_string member.type}[#{member.name}size];
483
+ for (int i = 0; i < #{member.name}size; i++) {
484
+ #{value}.#{member.name.camelize}[i] = #{decode_type member.declaration.type};
485
+ }
486
+ EOS
487
+ else
488
+ out.puts "#{value}.#{member.name.camelize} = #{decode_type member.declaration.type};"
489
+ end
490
+ out.puts '}' if member.type.sub_type == :optional
491
+ end
492
+
493
+ def decode_type(type)
494
+ case type
495
+ when AST::Typespecs::Int
496
+ 'stream.ReadInt()'
497
+ when AST::Typespecs::UnsignedInt
498
+ 'stream.ReadInt()'
499
+ when AST::Typespecs::Hyper
500
+ 'stream.ReadLong()'
501
+ when AST::Typespecs::UnsignedHyper
502
+ 'stream.ReadLong()'
503
+ when AST::Typespecs::Float
504
+ 'stream.ReadFloat()'
505
+ when AST::Typespecs::Double
506
+ 'stream.ReadDouble()'
507
+ when AST::Typespecs::Quadruple
508
+ raise 'cannot render quadruple in c#'
509
+ when AST::Typespecs::Bool
510
+ 'stream.ReadInt() == 1 ? true : false'
511
+ when AST::Typespecs::String
512
+ 'stream.ReadString()'
513
+ when AST::Typespecs::Simple
514
+ "#{name type.resolved_type}.Decode(stream)"
515
+ when AST::Concerns::NestedDefinition
516
+ "#{name type}.Decode(stream)"
517
+ else
518
+ raise "Unknown typespec: #{type.class.name}"
519
+ end
520
+ end
521
+
522
+ def decl_string(decl)
523
+ case decl
524
+ when AST::Declarations::Opaque
525
+ 'byte[]'
526
+ when AST::Declarations::String
527
+ 'String'
528
+ when AST::Declarations::Array
529
+ "#{type_string decl.type}[]"
530
+ when AST::Declarations::Optional
531
+ type_string(decl.type).to_s
532
+ when AST::Declarations::Simple
533
+ type_string(decl.type)
534
+ else
535
+ raise "Unknown declaration type: #{decl.class.name}"
536
+ end
537
+ end
538
+
539
+ def type_string(type)
540
+ case type
541
+ when AST::Typespecs::Int
542
+ 'int'
543
+ when AST::Typespecs::UnsignedInt
544
+ 'int'
545
+ when AST::Typespecs::Hyper
546
+ 'long'
547
+ when AST::Typespecs::UnsignedHyper
548
+ 'long'
549
+ when AST::Typespecs::Float
550
+ 'float'
551
+ when AST::Typespecs::Double
552
+ 'double'
553
+ when AST::Typespecs::Quadruple
554
+ 'Tuple'
555
+ when AST::Typespecs::Bool
556
+ 'bool'
557
+ when AST::Typespecs::Opaque
558
+ "Byte[#{type.size}]"
559
+ when AST::Typespecs::Simple
560
+ name type.resolved_type
561
+ when AST::Concerns::NestedDefinition
562
+ name type
563
+ else
564
+ raise "Unknown typespec: #{type.class.name}"
565
+ end
566
+ end
567
+
568
+ def name(named)
569
+ parent = name named.parent_defn if named.is_a?(AST::Concerns::NestedDefinition)
570
+ result = named.name.camelize
571
+
572
+ "#{parent}#{result}"
573
+ end
574
+
575
+ def name_string(name)
576
+ name.camelize
577
+ end
578
+ end
579
+ end
580
+ end
@@ -164,7 +164,7 @@ module Xdrgen
164
164
  parent = name named.parent_defn if named.is_a?(AST::Concerns::NestedDefinition)
165
165
 
166
166
  # NOTE: classify will strip plurality, so we restore it if necessary
167
- plural = named.name.downcase.pluralize == named.name.downcase
167
+ plural = named.name.underscore.downcase.pluralize == named.name.underscore.downcase
168
168
  base = named.name.underscore.classify
169
169
  result = plural ? base.pluralize : base
170
170
 
@@ -305,33 +305,77 @@ module Xdrgen
305
305
  out.puts <<-EOS.strip_heredoc
306
306
  @Override
307
307
  public boolean equals(Object object) {
308
- if (object == null || !(object instanceof #{type})) {
308
+ if (!(object instanceof #{type})) {
309
309
  return false;
310
310
  }
311
311
 
312
312
  #{type} other = (#{type}) object;
313
313
  return #{equalExpression};
314
314
  }
315
+
315
316
  EOS
316
317
 
318
+ out.puts "public static final class Builder {"
319
+ out.indent do
320
+ struct.members.map { |m|
321
+ out.puts "private #{decl_string(m.declaration)} #{m.name};"
322
+ }
323
+
324
+ struct.members.map { |m|
325
+ out.puts <<-EOS.strip_heredoc
326
+
327
+ public Builder #{m.name}(#{decl_string(m.declaration)} #{m.name}) {
328
+ this.#{m.name} = #{m.name};
329
+ return this;
330
+ }
331
+ EOS
332
+ }
333
+
334
+ end
335
+
336
+
337
+ out.indent do
338
+ out.break
339
+ out.puts "public #{name struct} build() {"
340
+ out.indent do
341
+ out.puts "#{name struct} val = new #{name struct}();"
342
+ struct.members.map { |m|
343
+ out.puts "val.set#{m.name.slice(0,1).capitalize+m.name.slice(1..-1)}(#{m.name});"
344
+ }
345
+ out.puts "return val;"
346
+ end
347
+ out.puts "}"
348
+ end
349
+ out.puts "}"
317
350
  out.break
318
351
  end
319
352
 
320
353
  def render_typedef(typedef, out)
321
354
  out.puts <<-EOS.strip_heredoc
322
355
  private #{decl_string typedef.declaration} #{typedef.name};
356
+
357
+ public #{typedef.name.camelize}() {}
358
+
359
+ public #{typedef.name.camelize}(#{decl_string typedef.declaration} #{typedef.name}) {
360
+ this.#{typedef.name} = #{typedef.name};
361
+ }
362
+
323
363
  public #{decl_string typedef.declaration} get#{typedef.name.slice(0,1).capitalize+typedef.name.slice(1..-1)}() {
324
364
  return this.#{typedef.name};
325
365
  }
366
+
326
367
  public void set#{typedef.name.slice(0,1).capitalize+typedef.name.slice(1..-1)}(#{decl_string typedef.declaration} value) {
327
368
  this.#{typedef.name} = value;
328
369
  }
329
- EOS
330
370
 
371
+ EOS
331
372
 
332
373
  out.puts "public static void encode(XdrDataOutputStream stream, #{name typedef} encoded#{name typedef}) throws IOException {"
333
- encode_member "encoded#{name typedef}", typedef, out
374
+ out.indent do
375
+ encode_member "encoded#{name typedef}", typedef, out
376
+ end
334
377
  out.puts "}"
378
+ out.break
335
379
 
336
380
  out.puts <<-EOS.strip_heredoc
337
381
  public void encode(XdrDataOutputStream stream) throws IOException {
@@ -343,11 +387,12 @@ module Xdrgen
343
387
  public static #{name typedef} decode(XdrDataInputStream stream) throws IOException {
344
388
  #{name typedef} decoded#{name typedef} = new #{name typedef}();
345
389
  EOS
346
- decode_member "decoded#{name typedef}", typedef, out
347
390
  out.indent do
391
+ decode_member "decoded#{name typedef}", typedef, out
348
392
  out.puts "return decoded#{name typedef};"
349
393
  end
350
394
  out.puts "}"
395
+ out.break
351
396
 
352
397
  hash_coder_for_decl =
353
398
  if is_decl_array(typedef.declaration)
@@ -360,6 +405,7 @@ module Xdrgen
360
405
  public int hashCode() {
361
406
  return #{hash_coder_for_decl}(this.#{typedef.name});
362
407
  }
408
+
363
409
  EOS
364
410
 
365
411
  equals_for_decl =
@@ -372,7 +418,7 @@ module Xdrgen
372
418
  out.puts <<-EOS.strip_heredoc
373
419
  @Override
374
420
  public boolean equals(Object object) {
375
- if (object == null || !(object instanceof #{type})) {
421
+ if (!(object instanceof #{type})) {
376
422
  return false;
377
423
  }
378
424
 
@@ -405,6 +451,54 @@ module Xdrgen
405
451
  }
406
452
  EOS
407
453
  end
454
+ out.break
455
+
456
+ out.puts "public static final class Builder {"
457
+ out.indent do
458
+ out.puts "private #{type_string union.discriminant.type} discriminant;"
459
+ union.arms.each do |arm|
460
+ next if arm.void?
461
+ out.puts "private #{decl_string(arm.declaration)} #{arm.name};"
462
+ end
463
+ out.break
464
+
465
+ out.puts <<-EOS.strip_heredoc
466
+ public Builder discriminant(#{type_string union.discriminant.type} discriminant) {
467
+ this.discriminant = discriminant;
468
+ return this;
469
+ }
470
+ EOS
471
+
472
+ union.arms.each do |arm|
473
+ next if arm.void?
474
+ out.puts <<-EOS.strip_heredoc
475
+
476
+ public Builder #{arm.name}(#{decl_string(arm.declaration)} #{arm.name}) {
477
+ this.#{arm.name} = #{arm.name};
478
+ return this;
479
+ }
480
+ EOS
481
+ end
482
+ end
483
+
484
+ out.indent do
485
+ out.break
486
+ out.puts "public #{name union} build() {"
487
+ out.indent do
488
+ out.puts "#{name union} val = new #{name union}();"
489
+ out.puts "val.setDiscriminant(discriminant);"
490
+ union.arms.each do |arm|
491
+ next if arm.void?
492
+ out.puts "val.set#{arm.name.slice(0,1).capitalize+arm.name.slice(1..-1)}(#{arm.name});"
493
+ end
494
+ out.puts "return val;"
495
+ end
496
+ out.puts "}"
497
+ end
498
+ out.puts "}"
499
+ out.break
500
+
501
+
408
502
  out.puts "public static void encode(XdrDataOutputStream stream, #{name union} encoded#{name union}) throws IOException {"
409
503
  out.puts('//' + union.discriminant.type.class.to_s)
410
504
  out.puts("//" + type_string(union.discriminant.type))
@@ -543,7 +637,7 @@ module Xdrgen
543
637
  out.puts <<-EOS.strip_heredoc
544
638
  @Override
545
639
  public boolean equals(Object object) {
546
- if (object == null || !(object instanceof #{type})) {
640
+ if (!(object instanceof #{type})) {
547
641
  return false;
548
642
  }
549
643
 
@@ -178,7 +178,7 @@ module Xdrgen
178
178
  # "BEGIN_SPONSORING_FUTURE_RESERVEs" == "BEGIN_SPONSORING_FUTURE_RESERVES"
179
179
  # => false
180
180
  #
181
- plural = named.name.downcase.pluralize == named.name.downcase
181
+ plural = named.name.underscore.downcase.pluralize == named.name.underscore.downcase
182
182
  base = named.name.underscore.classify
183
183
  result = plural ? base.pluralize : base
184
184
 
@@ -1,3 +1,3 @@
1
1
  module Xdrgen
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.1"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: xdrgen
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Scott Fleckenstein
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-10-06 00:00:00.000000000 Z
11
+ date: 2021-08-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: treetop
@@ -136,7 +136,7 @@ dependencies:
136
136
  - - ">="
137
137
  - !ruby/object:Gem::Version
138
138
  version: '0'
139
- description:
139
+ description:
140
140
  email:
141
141
  - scott@stellar.org
142
142
  executables:
@@ -144,8 +144,8 @@ executables:
144
144
  extensions: []
145
145
  extra_rdoc_files: []
146
146
  files:
147
+ - ".github/workflows/ruby.yml"
147
148
  - ".gitignore"
148
- - ".travis.yml"
149
149
  - Gemfile
150
150
  - Guardfile
151
151
  - LICENSE.txt
@@ -209,6 +209,7 @@ files:
209
209
  - lib/xdrgen/compilation.rb
210
210
  - lib/xdrgen/generators.rb
211
211
  - lib/xdrgen/generators/base.rb
212
+ - lib/xdrgen/generators/csharp.rb
212
213
  - lib/xdrgen/generators/elixir.rb
213
214
  - lib/xdrgen/generators/go.rb
214
215
  - lib/xdrgen/generators/java.rb
@@ -258,7 +259,7 @@ homepage: http://github.com/stellar/xdrgen
258
259
  licenses:
259
260
  - ISC
260
261
  metadata: {}
261
- post_install_message:
262
+ post_install_message:
262
263
  rdoc_options: []
263
264
  require_paths:
264
265
  - lib
@@ -273,8 +274,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
273
274
  - !ruby/object:Gem::Version
274
275
  version: '0'
275
276
  requirements: []
276
- rubygems_version: 3.0.3
277
- signing_key:
277
+ rubygems_version: 3.2.15
278
+ signing_key:
278
279
  specification_version: 4
279
280
  summary: An XDR code generator
280
281
  test_files:
data/.travis.yml DELETED
@@ -1,4 +0,0 @@
1
- language: ruby
2
- script: bundle exec rspec
3
- rvm:
4
- - 2.7.0