red-flatbuffers 0.0.1
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.
- checksums.yaml +7 -0
- data/README.md +84 -0
- data/bin/rbflatc +20 -0
- data/doc/text/apache-2.0.txt +202 -0
- data/doc/text/news.md +5 -0
- data/lib/flatbuffers/command/rbflatc.rb +60 -0
- data/lib/flatbuffers/enum.rb +49 -0
- data/lib/flatbuffers/flags.rb +83 -0
- data/lib/flatbuffers/generator.rb +585 -0
- data/lib/flatbuffers/inspectable.rb +41 -0
- data/lib/flatbuffers/reflection/advanced_features.rb +19 -0
- data/lib/flatbuffers/reflection/base_type.rb +34 -0
- data/lib/flatbuffers/reflection/enum.rb +75 -0
- data/lib/flatbuffers/reflection/enum_val.rb +56 -0
- data/lib/flatbuffers/reflection/field.rb +121 -0
- data/lib/flatbuffers/reflection/key_value.rb +27 -0
- data/lib/flatbuffers/reflection/object.rb +81 -0
- data/lib/flatbuffers/reflection/rpccall.rb +56 -0
- data/lib/flatbuffers/reflection/schema.rb +91 -0
- data/lib/flatbuffers/reflection/schema_file.rb +35 -0
- data/lib/flatbuffers/reflection/service.rb +60 -0
- data/lib/flatbuffers/reflection/type.rb +64 -0
- data/lib/flatbuffers/struct.rb +26 -0
- data/lib/flatbuffers/table.rb +34 -0
- data/lib/flatbuffers/union.rb +62 -0
- data/lib/flatbuffers/version.rb +17 -0
- data/lib/flatbuffers/view.rb +176 -0
- data/lib/flatbuffers.rb +20 -0
- data/red-flatbuffers.gemspec +46 -0
- metadata +111 -0
|
@@ -0,0 +1,585 @@
|
|
|
1
|
+
# Copyright 2025 Sutou Kouhei <kou@clear-code.com>
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
require "fileutils"
|
|
16
|
+
require "pathname"
|
|
17
|
+
|
|
18
|
+
require_relative "reflection/schema"
|
|
19
|
+
|
|
20
|
+
module FlatBuffers
|
|
21
|
+
class Generator
|
|
22
|
+
module NameConvertable
|
|
23
|
+
private
|
|
24
|
+
def denamespace(name)
|
|
25
|
+
name.split(".")
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def to_camel_case(name)
|
|
29
|
+
name.split("_").collect do |component|
|
|
30
|
+
component[0] = component[0].upcase
|
|
31
|
+
component
|
|
32
|
+
end.join
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def to_snake_case(name)
|
|
36
|
+
snake_case = +""
|
|
37
|
+
previous_char = +""
|
|
38
|
+
name.each_char do |char|
|
|
39
|
+
if not snake_case.empty? and
|
|
40
|
+
snake_case[-1] != "_" and
|
|
41
|
+
char.downcase != char and
|
|
42
|
+
previous_char.upcase != previous_char
|
|
43
|
+
snake_case << "_"
|
|
44
|
+
end
|
|
45
|
+
snake_case << char
|
|
46
|
+
previous_char = char
|
|
47
|
+
end
|
|
48
|
+
snake_case
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def to_upper_snake_case(name)
|
|
52
|
+
to_snake_case(name).upcase
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def to_lower_snake_case(name)
|
|
56
|
+
to_snake_case(name).downcase
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def to_module_name(name)
|
|
60
|
+
to_camel_case(name)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def to_class_name(name)
|
|
64
|
+
to_camel_case(name)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def to_namespaced_class_name(namespaces, name)
|
|
68
|
+
components = namespaces.collect {|namespace| to_module_name(namespace)}
|
|
69
|
+
components << to_class_name(name)
|
|
70
|
+
components.join("::")
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def to_constant_name(name)
|
|
74
|
+
to_upper_snake_case(name)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def to_variable_name(name)
|
|
78
|
+
to_lower_snake_case(name)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def to_method_name(name)
|
|
82
|
+
to_lower_snake_case(name)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def to_path(name)
|
|
86
|
+
to_lower_snake_case(name)
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
include NameConvertable
|
|
91
|
+
|
|
92
|
+
class Writer
|
|
93
|
+
include NameConvertable
|
|
94
|
+
|
|
95
|
+
def initialize(schema, target)
|
|
96
|
+
@schema = schema
|
|
97
|
+
@target = target
|
|
98
|
+
@indent = +""
|
|
99
|
+
@requires = []
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def add_require(path)
|
|
103
|
+
@requires |= [path]
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def start(output_dir)
|
|
107
|
+
output_path = output_dir
|
|
108
|
+
components = denamespace(@target.name)
|
|
109
|
+
components[0..-2].each do |component|
|
|
110
|
+
output_path += to_path(component)
|
|
111
|
+
end
|
|
112
|
+
output_path += "#{to_path(components.last)}.rb"
|
|
113
|
+
FileUtils.mkdir_p(output_path.parent.to_s)
|
|
114
|
+
output_path.open("w") do |output|
|
|
115
|
+
@output = output
|
|
116
|
+
write_header
|
|
117
|
+
yield
|
|
118
|
+
@output = nil
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def indent
|
|
123
|
+
@indent << " "
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def unindent
|
|
127
|
+
@indent = @indent[0..-3]
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def <<(line)
|
|
131
|
+
if line.empty?
|
|
132
|
+
@output << "\n"
|
|
133
|
+
else
|
|
134
|
+
@output << @indent << line << "\n"
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def end
|
|
139
|
+
unindent
|
|
140
|
+
self << "end"
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
private
|
|
144
|
+
def write_header
|
|
145
|
+
self << "# Automatically generated. Don't modify manually."
|
|
146
|
+
self << "#"
|
|
147
|
+
self << "# Red FlatBuffers version: #{FlatBuffers::VERSION}"
|
|
148
|
+
declaration_file = @target.declaration_file
|
|
149
|
+
unless declaration_file.empty?
|
|
150
|
+
self << "# Declared by: #{declaration_file}"
|
|
151
|
+
end
|
|
152
|
+
root_table = @schema.root_table
|
|
153
|
+
if root_table
|
|
154
|
+
root_type = root_table.name
|
|
155
|
+
root_file = root_table.declaration_file
|
|
156
|
+
self << "# Rooting type: #{root_type} (#{root_file})"
|
|
157
|
+
end
|
|
158
|
+
self << ""
|
|
159
|
+
self << "require \"flatbuffers\""
|
|
160
|
+
@requires.each do |require|
|
|
161
|
+
self << "require_relative \"#{require}\""
|
|
162
|
+
end
|
|
163
|
+
self << ""
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def initialize(input)
|
|
168
|
+
@schema = Reflection::Schema.new(input)
|
|
169
|
+
self.output_dir = Pathname(".")
|
|
170
|
+
self.outer_namespaces = nil
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
def output_dir=(dir)
|
|
174
|
+
dir = Pathname(dir) unless dir.is_a?(Pathname)
|
|
175
|
+
@output_dir = dir
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def outer_namespaces=(namespaces)
|
|
179
|
+
@outer_namespaces = namespaces
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
def generate
|
|
183
|
+
generate_enums
|
|
184
|
+
generate_objects
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
private
|
|
188
|
+
def generate_enums
|
|
189
|
+
@schema.enums.each do |enum|
|
|
190
|
+
writer = Writer.new(@schema, enum)
|
|
191
|
+
writer.start(@output_dir) do
|
|
192
|
+
generate_enum(writer, enum)
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
def start_modules(writer, namespaces)
|
|
198
|
+
@outer_namespaces&.each do |ns|
|
|
199
|
+
writer << "module #{ns}"
|
|
200
|
+
writer.indent
|
|
201
|
+
end
|
|
202
|
+
namespaces.each do |ns|
|
|
203
|
+
writer << "module #{to_module_name(ns)}"
|
|
204
|
+
writer.indent
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
def end_modules(writer, namespaces)
|
|
209
|
+
namespaces.each do |ns|
|
|
210
|
+
writer.end
|
|
211
|
+
end
|
|
212
|
+
@outer_namespaces&.each do |ns|
|
|
213
|
+
writer.end
|
|
214
|
+
end
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
def generate_enum(writer, enum)
|
|
218
|
+
*namespaces, name = denamespace(enum.name)
|
|
219
|
+
|
|
220
|
+
start_modules(writer, namespaces)
|
|
221
|
+
|
|
222
|
+
if enum.union?
|
|
223
|
+
parent = "::FlatBuffers::Union"
|
|
224
|
+
else
|
|
225
|
+
attributes = enum.attributes
|
|
226
|
+
if have_attribute?(attributes, "bit_flags")
|
|
227
|
+
parent = "::FlatBuffers::Flags"
|
|
228
|
+
else
|
|
229
|
+
parent = "::FlatBuffers::Enum"
|
|
230
|
+
end
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
generate_documentation(writer, enum.documentation)
|
|
234
|
+
writer << "class #{to_class_name(name)} < #{parent}"
|
|
235
|
+
writer.indent
|
|
236
|
+
enum.values.each do |value|
|
|
237
|
+
generate_documentation(writer, value.documentation)
|
|
238
|
+
ruby_name = to_ruby_code(value.name)
|
|
239
|
+
ruby_constant_name = to_constant_name(value.name)
|
|
240
|
+
ruby_value = to_ruby_code(value.value)
|
|
241
|
+
if enum.union?
|
|
242
|
+
union = @schema.objects[value.union_type.index]
|
|
243
|
+
*union_namespaces, union_name = denamespace(union.name)
|
|
244
|
+
klass = "::#{to_namespaced_class_name(union_namespaces, union_name)}"
|
|
245
|
+
relative_union_namespaces =
|
|
246
|
+
resolve_namespaces(union_namespaces, namespaces)
|
|
247
|
+
path_components = relative_union_namespaces.collect do |ns|
|
|
248
|
+
to_path(ns)
|
|
249
|
+
end
|
|
250
|
+
path_components << to_path(union_name)
|
|
251
|
+
path = File.join(*path_components)
|
|
252
|
+
# NAME = register("Name", value, "ClassName", "path")
|
|
253
|
+
writer << ("#{ruby_constant_name} = register(" +
|
|
254
|
+
"#{ruby_name}, " +
|
|
255
|
+
"#{ruby_value}, " +
|
|
256
|
+
"#{to_ruby_code(klass)}, " +
|
|
257
|
+
"#{to_ruby_code(path)})")
|
|
258
|
+
else
|
|
259
|
+
# NAME = register("Name", value)
|
|
260
|
+
writer << ("#{ruby_constant_name} = " +
|
|
261
|
+
"register(#{ruby_name}, #{ruby_value})")
|
|
262
|
+
end
|
|
263
|
+
end
|
|
264
|
+
if enum.union?
|
|
265
|
+
writer << "\n"
|
|
266
|
+
writer << "private def require_table_class"
|
|
267
|
+
writer.indent
|
|
268
|
+
writer << "require_relative @require_path"
|
|
269
|
+
writer.end
|
|
270
|
+
end
|
|
271
|
+
writer.end
|
|
272
|
+
|
|
273
|
+
end_modules(writer, namespaces)
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
def generate_objects
|
|
277
|
+
@schema.objects.each do |object|
|
|
278
|
+
writer = Writer.new(@schema, object)
|
|
279
|
+
detect_object_dependencies(writer, object)
|
|
280
|
+
writer.start(@output_dir) do
|
|
281
|
+
generate_object(writer, object)
|
|
282
|
+
end
|
|
283
|
+
end
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
def detect_object_dependencies(writer, object)
|
|
287
|
+
*base_namespaces, _name = denamespace(object.name)
|
|
288
|
+
object.fields&.each do |field|
|
|
289
|
+
next if field.deprecated?
|
|
290
|
+
|
|
291
|
+
type = field.type
|
|
292
|
+
base_type = type.base_type
|
|
293
|
+
case base_type
|
|
294
|
+
when Reflection::BaseType::UTYPE,
|
|
295
|
+
Reflection::BaseType::BOOL,
|
|
296
|
+
Reflection::BaseType::BYTE,
|
|
297
|
+
Reflection::BaseType::UBYTE,
|
|
298
|
+
Reflection::BaseType::SHORT,
|
|
299
|
+
Reflection::BaseType::USHORT,
|
|
300
|
+
Reflection::BaseType::INT,
|
|
301
|
+
Reflection::BaseType::UINT,
|
|
302
|
+
Reflection::BaseType::LONG,
|
|
303
|
+
Reflection::BaseType::ULONG
|
|
304
|
+
next if type.index < 0
|
|
305
|
+
target = @schema.enums[type.index]
|
|
306
|
+
when Reflection::BaseType::OBJ
|
|
307
|
+
target = @schema.objects[type.index]
|
|
308
|
+
next if target.name == object.name
|
|
309
|
+
when Reflection::BaseType::ARRAY,
|
|
310
|
+
Reflection::BaseType::VECTOR
|
|
311
|
+
element_base_type = type.element
|
|
312
|
+
next unless element_base_type == Reflection::BaseType::OBJ
|
|
313
|
+
target = @schema.objects[type.index]
|
|
314
|
+
next if target.name == object.name
|
|
315
|
+
else
|
|
316
|
+
next
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
*namespaces, name = denamespace(target.name)
|
|
320
|
+
relative_namespaces = resolve_namespaces(namespaces, base_namespaces)
|
|
321
|
+
components = relative_namespaces.collect {|ns| to_path(ns)}
|
|
322
|
+
components << to_path(name)
|
|
323
|
+
path = File.join(*components)
|
|
324
|
+
writer.add_require(path)
|
|
325
|
+
end
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
def generate_object(writer, object)
|
|
329
|
+
*namespaces, name = denamespace(object.name)
|
|
330
|
+
|
|
331
|
+
start_modules(writer, namespaces)
|
|
332
|
+
|
|
333
|
+
if object.struct?
|
|
334
|
+
parent = "::FlatBuffers::Struct"
|
|
335
|
+
else
|
|
336
|
+
parent = "::FlatBuffers::Table"
|
|
337
|
+
end
|
|
338
|
+
generate_documentation(writer, object.documentation)
|
|
339
|
+
writer << "class #{to_class_name(name)} < #{parent}"
|
|
340
|
+
writer.indent
|
|
341
|
+
|
|
342
|
+
n_processed_fields = 0
|
|
343
|
+
object.fields&.each do |field|
|
|
344
|
+
# Skip writing deprecated fields altogether.
|
|
345
|
+
next if field.deprecated?
|
|
346
|
+
|
|
347
|
+
writer << "" if n_processed_fields > 0
|
|
348
|
+
|
|
349
|
+
method_name = to_method_name(field.name)
|
|
350
|
+
type = field.type
|
|
351
|
+
base_type = type.base_type
|
|
352
|
+
if base_type == Reflection::BaseType::BOOL
|
|
353
|
+
method_name = "#{method_name}?".delete_prefix("is_")
|
|
354
|
+
end
|
|
355
|
+
generate_documentation(writer, field.documentation)
|
|
356
|
+
writer << "def #{method_name}"
|
|
357
|
+
writer.indent
|
|
358
|
+
|
|
359
|
+
ruby_field_offset = to_ruby_code(field.offset)
|
|
360
|
+
field_offset_direct_code = "field_offset = #{ruby_field_offset}"
|
|
361
|
+
field_offset_virtual_code =
|
|
362
|
+
"field_offset = @view.unpack_virtual_offset(#{ruby_field_offset})"
|
|
363
|
+
return_default_virtual_code =
|
|
364
|
+
"return #{to_ruby_code(default_value(field))} if field_offset.zero?"
|
|
365
|
+
unpack_method = "@view.unpack_#{to_method_name(base_type.name)}"
|
|
366
|
+
|
|
367
|
+
case base_type
|
|
368
|
+
when Reflection::BaseType::UTYPE,
|
|
369
|
+
Reflection::BaseType::BOOL,
|
|
370
|
+
Reflection::BaseType::BYTE,
|
|
371
|
+
Reflection::BaseType::UBYTE,
|
|
372
|
+
Reflection::BaseType::SHORT,
|
|
373
|
+
Reflection::BaseType::USHORT,
|
|
374
|
+
Reflection::BaseType::INT,
|
|
375
|
+
Reflection::BaseType::UINT,
|
|
376
|
+
Reflection::BaseType::LONG,
|
|
377
|
+
Reflection::BaseType::ULONG,
|
|
378
|
+
Reflection::BaseType::FLOAT,
|
|
379
|
+
Reflection::BaseType::DOUBLE
|
|
380
|
+
if object.struct?
|
|
381
|
+
writer << field_offset_direct_code
|
|
382
|
+
if enum_type?(type)
|
|
383
|
+
writer << "enum_value = #{unpack_method}(field_offset)"
|
|
384
|
+
klass = resolve_class_name(type, base_type, namespaces)
|
|
385
|
+
writer << "#{klass}.try_convert(enum_value) || enum_value"
|
|
386
|
+
else
|
|
387
|
+
writer << "#{unpack_method}(field_offset)"
|
|
388
|
+
end
|
|
389
|
+
else
|
|
390
|
+
writer << field_offset_virtual_code
|
|
391
|
+
if enum_type?(type)
|
|
392
|
+
klass = resolve_class_name(type, base_type, namespaces)
|
|
393
|
+
writer << "if field_offset.zero?"
|
|
394
|
+
writer.indent
|
|
395
|
+
writer << "enum_value = #{to_ruby_code(default_value(field))}"
|
|
396
|
+
writer.unindent
|
|
397
|
+
writer << "else"
|
|
398
|
+
writer.indent
|
|
399
|
+
writer << "enum_value = #{unpack_method}(field_offset)"
|
|
400
|
+
writer.end
|
|
401
|
+
writer << "#{klass}.try_convert(enum_value) || enum_value"
|
|
402
|
+
else
|
|
403
|
+
writer << return_default_virtual_code
|
|
404
|
+
writer << ""
|
|
405
|
+
writer << "#{unpack_method}(field_offset)"
|
|
406
|
+
end
|
|
407
|
+
end
|
|
408
|
+
when Reflection::BaseType::STRING
|
|
409
|
+
writer << field_offset_virtual_code
|
|
410
|
+
writer << return_default_virtual_code
|
|
411
|
+
writer << ""
|
|
412
|
+
writer << "#{unpack_method}(field_offset)"
|
|
413
|
+
when Reflection::BaseType::OBJ
|
|
414
|
+
if object.struct?
|
|
415
|
+
writer << field_offset_direct_code
|
|
416
|
+
klass = resolve_class_name(type, base_type, namespaces)
|
|
417
|
+
writer << "@view.unpack_struct(#{klass}, field_offset)\n"
|
|
418
|
+
else
|
|
419
|
+
writer << field_offset_virtual_code
|
|
420
|
+
writer << return_default_virtual_code
|
|
421
|
+
writer << ""
|
|
422
|
+
field_object = @schema.objects[type.index]
|
|
423
|
+
klass = resolve_class_name(type, base_type, namespaces)
|
|
424
|
+
if field_object.struct?
|
|
425
|
+
writer << "@view.unpack_struct(#{klass}, field_offset)"
|
|
426
|
+
else
|
|
427
|
+
writer << "@view.unpack_table(#{klass}, field_offset)"
|
|
428
|
+
end
|
|
429
|
+
end
|
|
430
|
+
when Reflection::BaseType::UNION
|
|
431
|
+
writer << "type = #{to_method_name(field.name)}_type"
|
|
432
|
+
writer << "return nil if type.nil?"
|
|
433
|
+
writer << ""
|
|
434
|
+
writer << field_offset_virtual_code
|
|
435
|
+
writer << return_default_virtual_code
|
|
436
|
+
writer << "@view.unpack_union(type.table_class, field_offset)"
|
|
437
|
+
when Reflection::BaseType::ARRAY,
|
|
438
|
+
Reflection::BaseType::VECTOR
|
|
439
|
+
element_base_type = type.element
|
|
440
|
+
element_size = type.element_size
|
|
441
|
+
if element_base_type == Reflection::BaseType::OBJ
|
|
442
|
+
klass = resolve_class_name(type, element_base_type, namespaces)
|
|
443
|
+
element_object = @schema.objects[type.index]
|
|
444
|
+
if element_object.struct?
|
|
445
|
+
unpack_element_code =
|
|
446
|
+
"@view.unpack_struct(#{klass}, element_offset)"
|
|
447
|
+
else
|
|
448
|
+
unpack_element_code =
|
|
449
|
+
"@view.unpack_table(#{klass}, element_offset)"
|
|
450
|
+
end
|
|
451
|
+
else
|
|
452
|
+
unpack_method_name =
|
|
453
|
+
"unpack_#{to_method_name(element_base_type.name)}"
|
|
454
|
+
unpack_element_code = "@view.#{unpack_method_name}(element_offset)"
|
|
455
|
+
end
|
|
456
|
+
writer << field_offset_virtual_code
|
|
457
|
+
writer << return_default_virtual_code
|
|
458
|
+
writer << ""
|
|
459
|
+
writer << "element_size = #{to_ruby_code(element_size)}"
|
|
460
|
+
unpack_vector = "@view.unpack_vector(field_offset, element_size)"
|
|
461
|
+
writer << "#{unpack_vector} do |element_offset|"
|
|
462
|
+
writer.indent
|
|
463
|
+
writer << unpack_element_code
|
|
464
|
+
writer.end
|
|
465
|
+
end
|
|
466
|
+
writer.end
|
|
467
|
+
|
|
468
|
+
n_processed_fields += 1
|
|
469
|
+
end
|
|
470
|
+
|
|
471
|
+
writer.end # class
|
|
472
|
+
|
|
473
|
+
end_modules(writer, namespaces)
|
|
474
|
+
end
|
|
475
|
+
|
|
476
|
+
def generate_documentation(writer, documentation)
|
|
477
|
+
documentation&.each do |line|
|
|
478
|
+
writer << "\##{line}"
|
|
479
|
+
end
|
|
480
|
+
end
|
|
481
|
+
|
|
482
|
+
def have_attribute?(attributes, key)
|
|
483
|
+
return false if attributes.nil?
|
|
484
|
+
attributes.any? do |attribute|
|
|
485
|
+
attribute.key == key
|
|
486
|
+
end
|
|
487
|
+
end
|
|
488
|
+
|
|
489
|
+
def to_ruby_code(value)
|
|
490
|
+
case value
|
|
491
|
+
when String
|
|
492
|
+
value.dump
|
|
493
|
+
when Float
|
|
494
|
+
if value.nan?
|
|
495
|
+
"Float::NAN"
|
|
496
|
+
elsif value.infinite?
|
|
497
|
+
if value > 0
|
|
498
|
+
"Float::INFINITY"
|
|
499
|
+
else
|
|
500
|
+
"-Float::INFINITY"
|
|
501
|
+
end
|
|
502
|
+
else
|
|
503
|
+
value.to_s
|
|
504
|
+
end
|
|
505
|
+
when nil
|
|
506
|
+
"nil"
|
|
507
|
+
else
|
|
508
|
+
value.to_s
|
|
509
|
+
end
|
|
510
|
+
end
|
|
511
|
+
|
|
512
|
+
def default_value(field)
|
|
513
|
+
base_type = field.type.base_type
|
|
514
|
+
case base_type
|
|
515
|
+
when Reflection::BaseType::FLOAT,
|
|
516
|
+
Reflection::BaseType::DOUBLE
|
|
517
|
+
field.default_real
|
|
518
|
+
when Reflection::BaseType::BOOL
|
|
519
|
+
not field.default_integer.zero?
|
|
520
|
+
when Reflection::BaseType::UTYPE,
|
|
521
|
+
Reflection::BaseType::BYTE,
|
|
522
|
+
Reflection::BaseType::UBYTE,
|
|
523
|
+
Reflection::BaseType::SHORT,
|
|
524
|
+
Reflection::BaseType::USHORT,
|
|
525
|
+
Reflection::BaseType::INT,
|
|
526
|
+
Reflection::BaseType::UINT,
|
|
527
|
+
Reflection::BaseType::LONG,
|
|
528
|
+
Reflection::BaseType::ULONG
|
|
529
|
+
field.default_integer
|
|
530
|
+
else
|
|
531
|
+
nil
|
|
532
|
+
end
|
|
533
|
+
end
|
|
534
|
+
|
|
535
|
+
def scalar_type?(base_type)
|
|
536
|
+
Reflection::BaseType::UTYPE.value <= base_type.value and
|
|
537
|
+
base_type.value >= Reflection::BaseType::DOUBLE.value
|
|
538
|
+
end
|
|
539
|
+
|
|
540
|
+
def integer_type?(base_type)
|
|
541
|
+
Reflection::BaseType::UTYPE.value <= base_type.value and
|
|
542
|
+
base_type.value <= Reflection::BaseType::ULONG.value
|
|
543
|
+
end
|
|
544
|
+
|
|
545
|
+
def enum_type?(type)
|
|
546
|
+
integer_type?(type.base_type) and type.index >= 0
|
|
547
|
+
end
|
|
548
|
+
|
|
549
|
+
def resolve_namespaces(namespaces, base_namespaces)
|
|
550
|
+
resolved_namespaces = namespaces.dup
|
|
551
|
+
base_namespaces.size.times do |i|
|
|
552
|
+
base_namespace = base_namespaces[i]
|
|
553
|
+
if namespaces.empty? or namespaces[0] != base_namespace
|
|
554
|
+
i.step(base_namespaces.size - 1) do
|
|
555
|
+
resolved_namespaces.unshift("..")
|
|
556
|
+
end
|
|
557
|
+
break
|
|
558
|
+
end
|
|
559
|
+
resolved_namespaces.shift
|
|
560
|
+
end
|
|
561
|
+
resolved_namespaces
|
|
562
|
+
end
|
|
563
|
+
|
|
564
|
+
def resolve_class_name(type,
|
|
565
|
+
base_type,
|
|
566
|
+
base_namespaces)
|
|
567
|
+
if base_type == Reflection::BaseType::OBJ
|
|
568
|
+
target = @schema.objects[type.index]
|
|
569
|
+
else
|
|
570
|
+
target = @schema.enums[type.index]
|
|
571
|
+
end
|
|
572
|
+
*namespaces, name = denamespace(target.name)
|
|
573
|
+
relative_namespaces = resolve_namespaces(namespaces, base_namespaces)
|
|
574
|
+
in_same_namespace =
|
|
575
|
+
(relative_namespaces.empty? or relative_namespaces[0] != "..")
|
|
576
|
+
if in_same_namespace
|
|
577
|
+
# We can use relative hierarchy
|
|
578
|
+
to_namespaced_class_name(relative_namespaces, name)
|
|
579
|
+
else
|
|
580
|
+
# We need to use absolute hierarchy
|
|
581
|
+
"::#{to_namespaced_class_name(namespaces, name)}"
|
|
582
|
+
end
|
|
583
|
+
end
|
|
584
|
+
end
|
|
585
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Copyright 2025 Sutou Kouhei <kou@clear-code.com>
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
module FlatBuffers
|
|
16
|
+
module Inspectable
|
|
17
|
+
def inspect
|
|
18
|
+
inspected = +"<#{self.class}:"
|
|
19
|
+
public_methods(false).each do |name|
|
|
20
|
+
next unless method(name).arity.zero?
|
|
21
|
+
inspected << " #{name}=#{__send__(name).inspect}"
|
|
22
|
+
end
|
|
23
|
+
inspected << ">"
|
|
24
|
+
inspected
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def pretty_print(q)
|
|
28
|
+
q.object_group(self) do
|
|
29
|
+
targets = public_methods(false).select do |name|
|
|
30
|
+
method(name).arity.zero?
|
|
31
|
+
end
|
|
32
|
+
q.seplist(targets, lambda {q.text(",")}) do |name|
|
|
33
|
+
q.breakable
|
|
34
|
+
q.text(name.to_s)
|
|
35
|
+
q.text("=")
|
|
36
|
+
q.pp(__send__(name))
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Automatically generated. Don't modify manually.
|
|
2
|
+
#
|
|
3
|
+
# Red FlatBuffers version: 0.0.1
|
|
4
|
+
# Declared by: //reflection.fbs
|
|
5
|
+
# Rooting type: reflection.Schema (//reflection.fbs)
|
|
6
|
+
|
|
7
|
+
require "flatbuffers"
|
|
8
|
+
|
|
9
|
+
module FlatBuffers
|
|
10
|
+
module Reflection
|
|
11
|
+
# New schema language features that are not supported by old code generators.
|
|
12
|
+
class AdvancedFeatures < ::FlatBuffers::Flags
|
|
13
|
+
ADVANCED_ARRAY_FEATURES = register("AdvancedArrayFeatures", 1)
|
|
14
|
+
ADVANCED_UNION_FEATURES = register("AdvancedUnionFeatures", 2)
|
|
15
|
+
OPTIONAL_SCALARS = register("OptionalScalars", 4)
|
|
16
|
+
DEFAULT_VECTORS_AND_STRINGS = register("DefaultVectorsAndStrings", 8)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Automatically generated. Don't modify manually.
|
|
2
|
+
#
|
|
3
|
+
# Red FlatBuffers version: 0.0.1
|
|
4
|
+
# Declared by: //reflection.fbs
|
|
5
|
+
# Rooting type: reflection.Schema (//reflection.fbs)
|
|
6
|
+
|
|
7
|
+
require "flatbuffers"
|
|
8
|
+
|
|
9
|
+
module FlatBuffers
|
|
10
|
+
module Reflection
|
|
11
|
+
class BaseType < ::FlatBuffers::Enum
|
|
12
|
+
NONE = register("None", 0)
|
|
13
|
+
UTYPE = register("UType", 1)
|
|
14
|
+
BOOL = register("Bool", 2)
|
|
15
|
+
BYTE = register("Byte", 3)
|
|
16
|
+
UBYTE = register("UByte", 4)
|
|
17
|
+
SHORT = register("Short", 5)
|
|
18
|
+
USHORT = register("UShort", 6)
|
|
19
|
+
INT = register("Int", 7)
|
|
20
|
+
UINT = register("UInt", 8)
|
|
21
|
+
LONG = register("Long", 9)
|
|
22
|
+
ULONG = register("ULong", 10)
|
|
23
|
+
FLOAT = register("Float", 11)
|
|
24
|
+
DOUBLE = register("Double", 12)
|
|
25
|
+
STRING = register("String", 13)
|
|
26
|
+
VECTOR = register("Vector", 14)
|
|
27
|
+
OBJ = register("Obj", 15)
|
|
28
|
+
UNION = register("Union", 16)
|
|
29
|
+
ARRAY = register("Array", 17)
|
|
30
|
+
VECTOR64 = register("Vector64", 18)
|
|
31
|
+
MAX_BASE_TYPE = register("MaxBaseType", 19)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|