ynl 0.3.0 → 0.4.2
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 +4 -4
- data/CHANGELOG.md +15 -0
- data/Rakefile +7 -0
- data/lib/ynl/family.rb +15 -2
- data/lib/ynl/generator.rb +811 -64
- data/lib/ynl/models.rb +21 -10
- data/lib/ynl/parser.rb +109 -42
- data/lib/ynl/version.rb +1 -1
- data/lib/ynl.rb +32 -4
- data/sig/generated/ynl/family.rbs +24 -0
- data/sig/generated/ynl/generator.rbs +163 -0
- data/sig/generated/ynl/models.rbs +165 -0
- data/sig/generated/ynl/parser.rbs +62 -0
- data/sig/generated/ynl/version.rbs +5 -0
- data/sig/generated/ynl.rbs +119 -0
- metadata +10 -4
data/lib/ynl/models.rb
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
module Ynl
|
|
2
2
|
module Models
|
|
3
|
-
Family = ::Struct.new(:name, :protocol, :protonum, :doc,
|
|
3
|
+
Family = ::Struct.new(:name, :protocol, :version, :protonum, :doc,
|
|
4
4
|
:consts, :enums, :flags, :structs,
|
|
5
5
|
:attribute_sets, :sub_messages, :operations, :mcast_groups)
|
|
6
6
|
class Family
|
|
7
7
|
def resolve
|
|
8
8
|
structs.transform_values! {|s| s.resolve(self) }
|
|
9
|
+
sub_messages.transform_values! {|s| s.resolve(self) }
|
|
9
10
|
attribute_sets.transform_values! {|s| s.resolve(self) }
|
|
10
11
|
operations.transform_values! {|operation| operation.resolve(self) }
|
|
11
12
|
self
|
|
@@ -29,9 +30,16 @@ module Ynl
|
|
|
29
30
|
end
|
|
30
31
|
|
|
31
32
|
Const = ::Struct.new(:name, :value, :doc)
|
|
33
|
+
Check = ::Struct.new(:operation, :value)
|
|
32
34
|
|
|
33
35
|
class SubMessage
|
|
34
|
-
Format = ::Struct.new(:value, :attribute_set)
|
|
36
|
+
Format = ::Struct.new(:value, :fixed_header, :attribute_set) do
|
|
37
|
+
def resolve(f)
|
|
38
|
+
self.fixed_header = fixed_header.resolve(f) if fixed_header.is_a?(Thunk)
|
|
39
|
+
self.attribute_set = attribute_set.resolve(f) if attribute_set.is_a?(Thunk)
|
|
40
|
+
self
|
|
41
|
+
end
|
|
42
|
+
end
|
|
35
43
|
|
|
36
44
|
attr_reader :name, :formats
|
|
37
45
|
|
|
@@ -41,6 +49,7 @@ module Ynl
|
|
|
41
49
|
end
|
|
42
50
|
|
|
43
51
|
def resolve(f)
|
|
52
|
+
formats.map! { it.resolve(f) }
|
|
44
53
|
self
|
|
45
54
|
end
|
|
46
55
|
end
|
|
@@ -100,11 +109,16 @@ module Ynl
|
|
|
100
109
|
end
|
|
101
110
|
|
|
102
111
|
class AttributeSet
|
|
103
|
-
Attribute = ::Struct.new(:name, :type, :value, :checks, :doc) do
|
|
112
|
+
Attribute = ::Struct.new(:name, :type, :value, :checks, :doc, :multi_attr, :enum, :enum_as_flags) do
|
|
104
113
|
def resolve(f)
|
|
105
114
|
self.type = type.resolve(f)
|
|
115
|
+
self.enum = enum.resolve(f) if enum
|
|
106
116
|
self
|
|
107
117
|
end
|
|
118
|
+
|
|
119
|
+
def multi?
|
|
120
|
+
multi_attr
|
|
121
|
+
end
|
|
108
122
|
end
|
|
109
123
|
|
|
110
124
|
attr_reader :name, :name_prefix, :attributes, :doc
|
|
@@ -135,17 +149,14 @@ module Ynl
|
|
|
135
149
|
end
|
|
136
150
|
|
|
137
151
|
def attributes
|
|
138
|
-
|
|
139
|
-
# entries in subset-of attribute sets. Deduplicate by name here until the
|
|
140
|
-
# upstream specs are fixed.
|
|
141
|
-
@attributes.uniq {|attr| attr.fetch('name') }.map do |attr|
|
|
142
|
-
name = attr.fetch('name')
|
|
143
|
-
superset.attributes.find { it.name == name } or raise ParseError "No attribute with name #{name}"
|
|
144
|
-
end
|
|
152
|
+
@attributes
|
|
145
153
|
end
|
|
146
154
|
|
|
147
155
|
def resolve(f)
|
|
156
|
+
attributes.map! { it.resolve(f) }
|
|
148
157
|
self
|
|
158
|
+
rescue
|
|
159
|
+
raise ParseError, "Failed to resolve attribute subset: #{name}"
|
|
149
160
|
end
|
|
150
161
|
end
|
|
151
162
|
|
data/lib/ynl/parser.rb
CHANGED
|
@@ -4,6 +4,8 @@ require_relative 'models'
|
|
|
4
4
|
|
|
5
5
|
module Ynl
|
|
6
6
|
class Parser
|
|
7
|
+
# @param [String, #read] source
|
|
8
|
+
# @rbs (String | _Readable source) -> void
|
|
7
9
|
def initialize(source)
|
|
8
10
|
@yaml = YAML.load(source, aliases: true)
|
|
9
11
|
|
|
@@ -13,17 +15,24 @@ module Ynl
|
|
|
13
15
|
@structs = {}
|
|
14
16
|
|
|
15
17
|
@attribute_sets = {}
|
|
18
|
+
@attribute_definitions = {}
|
|
16
19
|
@sub_messages = {}
|
|
17
20
|
@operations = {}
|
|
18
21
|
@mcast_groups = {}
|
|
19
22
|
end
|
|
20
23
|
|
|
24
|
+
# @param [String, #to_path] path
|
|
25
|
+
# @return [Models::Family]
|
|
26
|
+
# @rbs (String | _PathLike path) -> Models::Family
|
|
21
27
|
def self.parse_file(path)
|
|
22
28
|
File.open(path) {|f| new(f) }.parse
|
|
23
29
|
end
|
|
24
30
|
|
|
31
|
+
# @return [Models::Family]
|
|
32
|
+
# @rbs () -> Models::Family
|
|
25
33
|
def parse
|
|
26
34
|
protocol = @yaml['protocol'] || 'genetlink'
|
|
35
|
+
version = @yaml.fetch('version', 1)
|
|
27
36
|
protonum = @yaml['protonum']
|
|
28
37
|
name = @yaml['name']
|
|
29
38
|
doc = translate_doc(@yaml['doc'])
|
|
@@ -86,6 +95,7 @@ module Ynl
|
|
|
86
95
|
Models::Family.new(
|
|
87
96
|
name:,
|
|
88
97
|
protocol:,
|
|
98
|
+
version:,
|
|
89
99
|
protonum:,
|
|
90
100
|
doc:,
|
|
91
101
|
consts: @consts,
|
|
@@ -106,9 +116,11 @@ module Ynl
|
|
|
106
116
|
@consts[v.name] = v
|
|
107
117
|
when 'enum'
|
|
108
118
|
v = parse_enum_flags(d, type: :enum)
|
|
119
|
+
reject_enum_flags_name_collision(v.name, @flags)
|
|
109
120
|
@enums[v.name] = v
|
|
110
121
|
when 'flags'
|
|
111
122
|
v = parse_enum_flags(d, type: :flags)
|
|
123
|
+
reject_enum_flags_name_collision(v.name, @enums)
|
|
112
124
|
@flags[v.name] = v
|
|
113
125
|
when 'struct'
|
|
114
126
|
v = parse_struct(d)
|
|
@@ -118,19 +130,33 @@ module Ynl
|
|
|
118
130
|
end
|
|
119
131
|
end
|
|
120
132
|
|
|
133
|
+
private def reject_enum_flags_name_collision(name, other_definitions)
|
|
134
|
+
return unless other_definitions.key?(name)
|
|
135
|
+
|
|
136
|
+
raise ParseError, "Definition #{name.inspect} cannot be both an enum and flags"
|
|
137
|
+
end
|
|
138
|
+
|
|
121
139
|
private def parse_const(d)
|
|
122
140
|
name = "#{d['name-prefix']}#{d.fetch('name')}"
|
|
123
|
-
|
|
141
|
+
value = d.fetch('value')
|
|
142
|
+
unless value.is_a?(Integer) || value.is_a?(String)
|
|
143
|
+
raise ParseError, "Constant value must be a string or an integer: #{name}"
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
Models::Const.new(name, value, translate_doc(d['doc']))
|
|
124
147
|
end
|
|
125
148
|
|
|
126
149
|
private def parse_enum_flags(d, type:)
|
|
127
150
|
cls = type == :enum ? Models::Enum : Models::Flags
|
|
128
151
|
result = cls.new(name: d.fetch('name'), doc: translate_doc(d['doc']))
|
|
129
152
|
|
|
130
|
-
start_value = d['start
|
|
131
|
-
|
|
153
|
+
start_value = d['value-start'] || 0
|
|
154
|
+
raw_value = start_value
|
|
132
155
|
|
|
133
156
|
d.fetch('entries').each do |v|
|
|
157
|
+
explicit_value = v.is_a?(Hash) ? v['value'] : nil
|
|
158
|
+
raw_value = explicit_value unless explicit_value.nil?
|
|
159
|
+
value = type == :enum ? raw_value : 1 << raw_value
|
|
134
160
|
case v
|
|
135
161
|
when String
|
|
136
162
|
entry = cls::Entry.new(name: v, value:)
|
|
@@ -142,7 +168,7 @@ module Ynl
|
|
|
142
168
|
|
|
143
169
|
result.entries << entry
|
|
144
170
|
|
|
145
|
-
|
|
171
|
+
raw_value += 1
|
|
146
172
|
|
|
147
173
|
rescue
|
|
148
174
|
raise ParseError, "Failed to parse enum/flags entry: #{v.fetch('name')}"
|
|
@@ -164,6 +190,7 @@ module Ynl
|
|
|
164
190
|
when 'binary'
|
|
165
191
|
Types::Binary.new(
|
|
166
192
|
struct: d['struct'] ? Models::Thunk.new {|f| f.structs.fetch(d['struct']) } : nil,
|
|
193
|
+
length: d['len'],
|
|
167
194
|
display_hint: d['display-hint'],
|
|
168
195
|
)
|
|
169
196
|
when 'pad'
|
|
@@ -184,10 +211,15 @@ module Ynl
|
|
|
184
211
|
byte_order: parse_byte_order(d['byte-order']),
|
|
185
212
|
)
|
|
186
213
|
when 'binary'
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
214
|
+
if d.key?('sub-type')
|
|
215
|
+
Types::PackedArray.new(sub_type: parse_packed_array_sub_type(d))
|
|
216
|
+
else
|
|
217
|
+
Types::Binary.new(
|
|
218
|
+
struct: d['struct'] ? Models::Thunk.new {|f| f.structs.fetch(d.fetch('struct')) } : nil,
|
|
219
|
+
length: nil,
|
|
220
|
+
display_hint: d['display-hint'],
|
|
221
|
+
)
|
|
222
|
+
end
|
|
191
223
|
when 'string'
|
|
192
224
|
Types::String.new
|
|
193
225
|
when 'nest'
|
|
@@ -205,7 +237,7 @@ module Ynl
|
|
|
205
237
|
type_values: d.fetch('type-value'),
|
|
206
238
|
)
|
|
207
239
|
else
|
|
208
|
-
Types::Binary.new(struct: nil, display_hint: nil)
|
|
240
|
+
Types::Binary.new(struct: nil, length: nil, display_hint: nil)
|
|
209
241
|
end
|
|
210
242
|
when 'sub-message'
|
|
211
243
|
Types::SubMessage.new(
|
|
@@ -238,6 +270,7 @@ module Ynl
|
|
|
238
270
|
when 'binary'
|
|
239
271
|
Types::Binary.new(
|
|
240
272
|
struct: nil,
|
|
273
|
+
length: nil,
|
|
241
274
|
display_hint: d['display-hint'],
|
|
242
275
|
)
|
|
243
276
|
when 'nest'
|
|
@@ -249,13 +282,26 @@ module Ynl
|
|
|
249
282
|
end
|
|
250
283
|
end
|
|
251
284
|
|
|
285
|
+
private def parse_packed_array_sub_type(d)
|
|
286
|
+
sub_type = d.fetch('sub-type')
|
|
287
|
+
case sub_type
|
|
288
|
+
when 'u8', 'u16', 'u32', 'u64', 's8', 's16', 's32', 's64', 'int'
|
|
289
|
+
Types::Scalar.new(
|
|
290
|
+
type: sub_type,
|
|
291
|
+
byte_order: parse_byte_order(d['byte-order']),
|
|
292
|
+
)
|
|
293
|
+
else
|
|
294
|
+
raise ParseError, "Unknown packed-array sub-type: #{sub_type}"
|
|
295
|
+
end
|
|
296
|
+
end
|
|
297
|
+
|
|
252
298
|
private def parse_byte_order(v)
|
|
253
299
|
case v
|
|
254
300
|
when nil
|
|
255
301
|
:host
|
|
256
302
|
when 'big-endian'
|
|
257
303
|
:big
|
|
258
|
-
when '
|
|
304
|
+
when 'little-endian'
|
|
259
305
|
:little
|
|
260
306
|
else
|
|
261
307
|
raise ParseError, "Unknown endian: #{v}"
|
|
@@ -288,21 +334,8 @@ module Ynl
|
|
|
288
334
|
|
|
289
335
|
private def parse_check(op, value_literal)
|
|
290
336
|
case op
|
|
291
|
-
when 'max'
|
|
292
|
-
value
|
|
293
|
-
return %{raise ArgumentError, "Value \#{it.inspect} is greater than maximum #{value}" unless it <= #{value}}
|
|
294
|
-
when 'min'
|
|
295
|
-
value = parse_value(value_literal)
|
|
296
|
-
return %{raise ArgumentError, "Value \#{it.inspect} is less than minimum #{value}" unless it >= #{value}}
|
|
297
|
-
when 'min-len'
|
|
298
|
-
value = parse_value(value_literal)
|
|
299
|
-
return %{raise ArgumentError, "Value \#{it.inspect} is shorter than minimum length #{value}" unless it.bytesize >= #{value}}
|
|
300
|
-
when 'max-len'
|
|
301
|
-
value = parse_value(value_literal)
|
|
302
|
-
return %{raise ArgumentError, "Value \#{it.inspect} is longer than maximum length #{value}" unless it.bytesize <= #{value}}
|
|
303
|
-
when 'exact-len'
|
|
304
|
-
value = parse_value(value_literal)
|
|
305
|
-
return %{raise ArgumentError, "Value \#{it.inspect} is not equal to length #{value}" unless it.bytesize == #{value}}
|
|
337
|
+
when 'max', 'min', 'min-len', 'max-len', 'exact-len'
|
|
338
|
+
Models::Check.new(operation: op, value: parse_value(value_literal))
|
|
306
339
|
when 'unterminated-ok'
|
|
307
340
|
return nil
|
|
308
341
|
else
|
|
@@ -322,7 +355,7 @@ module Ynl
|
|
|
322
355
|
(2 ** 31) - 1
|
|
323
356
|
when String
|
|
324
357
|
const = @consts[v] or raise ParseError, "Unknown value: #{v}"
|
|
325
|
-
const
|
|
358
|
+
const
|
|
326
359
|
else
|
|
327
360
|
raise ParseError, "Unknown value: #{v}"
|
|
328
361
|
end
|
|
@@ -332,38 +365,72 @@ module Ynl
|
|
|
332
365
|
name = d.fetch('name')
|
|
333
366
|
if subset_of = d['subset-of']
|
|
334
367
|
superset = @attribute_sets.fetch(subset_of)
|
|
335
|
-
|
|
368
|
+
inherited = @attribute_definitions.fetch(subset_of).to_h { [it.fetch('name'), it] }
|
|
369
|
+
definitions = d.fetch('attributes').uniq { it.fetch('name') }.map do |override|
|
|
370
|
+
parent = inherited.fetch(override.fetch('name'))
|
|
371
|
+
parent.merge(override).merge('value' => parent.fetch('value'))
|
|
372
|
+
end
|
|
373
|
+
attributes = definitions.filter_map { parse_attribute(it) }
|
|
374
|
+
result = Models::AttributeSubset.new(name:, superset:, attributes:, doc: translate_doc(d['doc']))
|
|
336
375
|
else
|
|
337
376
|
name_prefix = d['name_prefix']
|
|
338
377
|
result = Models::AttributeSet.new(name:, name_prefix:, doc: translate_doc(d['doc']))
|
|
339
378
|
value = 0
|
|
340
|
-
|
|
341
|
-
d.fetch('attributes').each do |v|
|
|
379
|
+
definitions = d.fetch('attributes').map do |v|
|
|
342
380
|
value = v.fetch('value', value + 1)
|
|
343
|
-
|
|
344
|
-
attribute = Models::AttributeSet::Attribute.new(name: v.fetch('name'), type: type, value:)
|
|
345
|
-
result.attributes << attribute
|
|
346
|
-
if checks = v['checks']
|
|
347
|
-
attribute.checks = parse_checks(checks)
|
|
348
|
-
end
|
|
349
|
-
end
|
|
350
|
-
rescue
|
|
351
|
-
raise ParseError, "Failed to parse attribute: #{v.fetch('name')}"
|
|
381
|
+
v.merge('value' => value)
|
|
352
382
|
end
|
|
383
|
+
result.attributes.concat(definitions.filter_map { parse_attribute(it) })
|
|
353
384
|
end
|
|
354
385
|
|
|
355
386
|
@attribute_sets[name] = result
|
|
387
|
+
@attribute_definitions[name] = definitions
|
|
356
388
|
|
|
357
|
-
rescue
|
|
358
|
-
raise ParseError, "Failed to parse attribute set
|
|
389
|
+
rescue => error
|
|
390
|
+
raise ParseError, "Failed to parse attribute set #{d.fetch('name')}: #{error.message}"
|
|
391
|
+
end
|
|
392
|
+
|
|
393
|
+
private def parse_attribute(d)
|
|
394
|
+
multi_attr = d.fetch('multi-attr', false)
|
|
395
|
+
unless multi_attr == true || multi_attr == false
|
|
396
|
+
raise ParseError, "multi-attr must be a boolean"
|
|
397
|
+
end
|
|
398
|
+
|
|
399
|
+
enum_as_flags = d.fetch('enum-as-flags', false)
|
|
400
|
+
unless enum_as_flags == true || enum_as_flags == false
|
|
401
|
+
raise ParseError, "enum-as-flags must be a boolean"
|
|
402
|
+
end
|
|
403
|
+
if enum_as_flags && !d['enum']
|
|
404
|
+
raise ParseError, "enum-as-flags requires enum"
|
|
405
|
+
end
|
|
406
|
+
|
|
407
|
+
return unless type = parse_attribute_type(d)
|
|
408
|
+
|
|
409
|
+
Models::AttributeSet::Attribute.new(
|
|
410
|
+
name: d.fetch('name'),
|
|
411
|
+
type:,
|
|
412
|
+
value: d.fetch('value'),
|
|
413
|
+
checks: (parse_checks(d['checks']) if d['checks']),
|
|
414
|
+
doc: translate_doc(d['doc']),
|
|
415
|
+
multi_attr:,
|
|
416
|
+
enum: d['enum']&.then { |ref| Models::Thunk.new {|f| f.find_type(ref) } },
|
|
417
|
+
enum_as_flags:,
|
|
418
|
+
)
|
|
419
|
+
rescue => error
|
|
420
|
+
raise ParseError, "Failed to parse attribute #{d.fetch('name')}: #{error.message}"
|
|
359
421
|
end
|
|
360
422
|
|
|
361
423
|
private def parse_sub_message(d)
|
|
362
424
|
name = d.fetch('name')
|
|
363
425
|
result = Models::SubMessage.new(name:)
|
|
364
426
|
d.fetch('formats', []).each do |fmt|
|
|
365
|
-
|
|
366
|
-
|
|
427
|
+
fixed_header = fmt['fixed-header']&.then do |ref|
|
|
428
|
+
Models::Thunk.new {|f| f.structs.fetch(ref) }
|
|
429
|
+
end
|
|
430
|
+
attr_set = fmt['attribute-set']&.then do |ref|
|
|
431
|
+
Models::Thunk.new {|f| f.attribute_sets.fetch(ref) }
|
|
432
|
+
end
|
|
433
|
+
result.formats << Models::SubMessage::Format.new(fmt.fetch('value'), fixed_header, attr_set)
|
|
367
434
|
end
|
|
368
435
|
@sub_messages[name] = result
|
|
369
436
|
end
|
data/lib/ynl/version.rb
CHANGED
data/lib/ynl.rb
CHANGED
|
@@ -1,12 +1,28 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Parser for YNL netlink specification
|
|
2
2
|
#
|
|
3
3
|
# See: https://www.kernel.org/doc/html/latest/userspace-api/netlink/specs.html
|
|
4
|
+
#-
|
|
4
5
|
|
|
5
6
|
require_relative 'ynl/family'
|
|
6
7
|
|
|
8
|
+
# Ynl parser and code generator. See {Family} for library entrypoint.
|
|
7
9
|
module Ynl
|
|
10
|
+
# @rbs!
|
|
11
|
+
# interface _Readable
|
|
12
|
+
# def read: () -> String
|
|
13
|
+
# end
|
|
14
|
+
#
|
|
15
|
+
# interface _Writable
|
|
16
|
+
# def write: (*String strings) -> untyped
|
|
17
|
+
# end
|
|
18
|
+
#
|
|
19
|
+
# interface _PathLike
|
|
20
|
+
# def to_path: () -> String
|
|
21
|
+
# end
|
|
22
|
+
|
|
8
23
|
class ParseError < StandardError; end
|
|
9
24
|
|
|
25
|
+
# @private
|
|
10
26
|
module Types
|
|
11
27
|
Scalar = Data.define(:type, :byte_order) do
|
|
12
28
|
def resolve(f)
|
|
@@ -27,13 +43,25 @@ module Ynl
|
|
|
27
43
|
end
|
|
28
44
|
end
|
|
29
45
|
Binary = Struct.new(:struct, :length, :display_hint) do
|
|
46
|
+
using Generator::Refinements
|
|
47
|
+
|
|
30
48
|
def resolve(f)
|
|
31
49
|
self.struct = struct.resolve(f) if self.struct
|
|
32
50
|
self
|
|
33
51
|
end
|
|
34
52
|
|
|
35
53
|
def rbs_type
|
|
36
|
-
'::String'
|
|
54
|
+
struct ? 'Structs::' + struct.name.as_class_name : '::String'
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
PackedArray = Struct.new(:sub_type) do
|
|
58
|
+
def resolve(f)
|
|
59
|
+
self.sub_type = sub_type.resolve(f)
|
|
60
|
+
self
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def rbs_type
|
|
64
|
+
"::Array[#{sub_type.rbs_type}]"
|
|
37
65
|
end
|
|
38
66
|
end
|
|
39
67
|
NestedAttributes = Struct.new(:attribute_set) do
|
|
@@ -69,7 +97,7 @@ module Ynl
|
|
|
69
97
|
end
|
|
70
98
|
|
|
71
99
|
def rbs_type
|
|
72
|
-
'::
|
|
100
|
+
'::Nl::SubMessage'
|
|
73
101
|
end
|
|
74
102
|
end
|
|
75
103
|
|
|
@@ -99,7 +127,7 @@ module Ynl
|
|
|
99
127
|
end
|
|
100
128
|
|
|
101
129
|
def rbs_type
|
|
102
|
-
'::
|
|
130
|
+
'::Nl::Bitfield32'
|
|
103
131
|
end
|
|
104
132
|
end
|
|
105
133
|
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Generated from lib/ynl/family.rb with RBS::Inline
|
|
2
|
+
|
|
3
|
+
module Ynl
|
|
4
|
+
# Entry points for generating family classes from YNL specifications.
|
|
5
|
+
class Family
|
|
6
|
+
# Builds a family class from a YNL specification file.
|
|
7
|
+
#
|
|
8
|
+
# @param [String, #to_path] path a path to a YNL specification file
|
|
9
|
+
# @return [Class<Nl::Family>] the generated family class
|
|
10
|
+
# @rbs (String | _PathLike path) -> Class
|
|
11
|
+
def self.build: (String | _PathLike path) -> Class
|
|
12
|
+
|
|
13
|
+
# Generates Ruby source code to define a family class from a YNL specification.
|
|
14
|
+
#
|
|
15
|
+
# @param [String, #read] source a YAML string or readable IO containing the YNL specification
|
|
16
|
+
# @param [#write] out the destination for the generated source code
|
|
17
|
+
# @option kwargs [String, nil] superclass the name of the generated class's superclass
|
|
18
|
+
# @option kwargs [String, nil] namespace the namespace in which to define the family class
|
|
19
|
+
# @option kwargs [String, nil] default_resolver the expression used as the default family resolver
|
|
20
|
+
# @return [String] the generated family class name
|
|
21
|
+
# @rbs (String | _Readable source, _Writable out, ?superclass: String?, ?namespace: String?, ?default_resolver: String?) -> String
|
|
22
|
+
def self.generate: (String | _Readable source, _Writable out, ?superclass: String?, ?namespace: String?, ?default_resolver: String?) -> String
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
# Generated from lib/ynl/generator.rb with RBS::Inline
|
|
2
|
+
|
|
3
|
+
module Ynl
|
|
4
|
+
# Generates Ruby code from a parsed YNL specification.
|
|
5
|
+
class Generator
|
|
6
|
+
# @private
|
|
7
|
+
module Refinements
|
|
8
|
+
WORD_DELIM: ::Regexp
|
|
9
|
+
|
|
10
|
+
def as_const_name: () -> untyped
|
|
11
|
+
|
|
12
|
+
def as_class_name: () -> untyped
|
|
13
|
+
|
|
14
|
+
def as_variable_name: () -> untyped
|
|
15
|
+
|
|
16
|
+
alias as_method_name as_variable_name
|
|
17
|
+
|
|
18
|
+
def as_string_literal: () -> untyped
|
|
19
|
+
|
|
20
|
+
def as_symbol_literal: () -> untyped
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
PRELUDE: untyped
|
|
24
|
+
|
|
25
|
+
OPERATION_FLAG_DOCS: untyped
|
|
26
|
+
|
|
27
|
+
KERNEL_DOC_REFERENCE: ::Regexp
|
|
28
|
+
|
|
29
|
+
# @rbs (Models::Family ynl, _Writable out) -> void
|
|
30
|
+
def initialize: (Models::Family ynl, _Writable out) -> void
|
|
31
|
+
|
|
32
|
+
# @rbs (?superclass: String?, ?namespace: String?, ?default_resolver: String?) -> void
|
|
33
|
+
def generate: (?superclass: String?, ?namespace: String?, ?default_resolver: String?) -> void
|
|
34
|
+
|
|
35
|
+
INDENT: untyped
|
|
36
|
+
|
|
37
|
+
NEWLINE: untyped
|
|
38
|
+
|
|
39
|
+
private def write: (*untyped str) -> untyped
|
|
40
|
+
|
|
41
|
+
private def indent: () -> untyped
|
|
42
|
+
|
|
43
|
+
private def emit_module: (untyped name) -> untyped
|
|
44
|
+
|
|
45
|
+
private def emit_class: (untyped name, ?untyped superclass) -> untyped
|
|
46
|
+
|
|
47
|
+
private def emit_singleton_class: () -> untyped
|
|
48
|
+
|
|
49
|
+
private def emit_const: (untyped name, untyped value, ?rbs: untyped, ?internal: untyped) -> untyped
|
|
50
|
+
|
|
51
|
+
private def emit_value_definitions: (untyped namespace, untyped definitions) -> untyped
|
|
52
|
+
|
|
53
|
+
private def enums_used_as_flags: () -> untyped
|
|
54
|
+
|
|
55
|
+
private def emit_getter: (untyped name, untyped expr) -> untyped
|
|
56
|
+
|
|
57
|
+
private def emit_internal: () -> untyped
|
|
58
|
+
|
|
59
|
+
private def emit_open: (raw: untyped, default_resolver: untyped, classname: untyped) -> untyped
|
|
60
|
+
|
|
61
|
+
private def emit_yard_open_params: (resolver: untyped, ?indentation: untyped) -> untyped
|
|
62
|
+
|
|
63
|
+
private def emit_comment: (untyped comment) -> untyped
|
|
64
|
+
|
|
65
|
+
private def operation_doc: (untyped operation) -> untyped
|
|
66
|
+
|
|
67
|
+
private def notification_operations: () -> untyped
|
|
68
|
+
|
|
69
|
+
private def notification_doc: (untyped operation) -> untyped
|
|
70
|
+
|
|
71
|
+
private def notification_layout: (untyped operation) -> untyped
|
|
72
|
+
|
|
73
|
+
private def emit_message_class: (untyped name, untyped message, fixed_header: untyped, attribute_set: untyped, doc: untyped) -> untyped
|
|
74
|
+
|
|
75
|
+
private def emit_sub_messages: () -> untyped
|
|
76
|
+
|
|
77
|
+
private def emit_sub_message_class: (untyped name, untyped format) -> untyped
|
|
78
|
+
|
|
79
|
+
private def parameter_rbs_type: (untyped param) -> untyped
|
|
80
|
+
|
|
81
|
+
private def parameter_yard_type: (untyped param) -> untyped
|
|
82
|
+
|
|
83
|
+
private def struct_member_rbs_type: (untyped type) -> untyped
|
|
84
|
+
|
|
85
|
+
private def struct_member_yard_type: (untyped type) -> untyped
|
|
86
|
+
|
|
87
|
+
private def input_rbs_type: (untyped type) -> untyped
|
|
88
|
+
|
|
89
|
+
private def input_yard_type: (untyped type) -> untyped
|
|
90
|
+
|
|
91
|
+
private def attribute_rbs_type: (untyped attribute) -> untyped
|
|
92
|
+
|
|
93
|
+
private def attribute_yard_type: (untyped attribute) -> untyped
|
|
94
|
+
|
|
95
|
+
private def attribute_doc: (untyped attribute) -> untyped
|
|
96
|
+
|
|
97
|
+
private def attribute_value_definition: (untyped attribute) -> untyped
|
|
98
|
+
|
|
99
|
+
private def sub_message_rbs_type: (untyped type) -> untyped
|
|
100
|
+
|
|
101
|
+
private def sub_message_yard_type: (untyped type) -> untyped
|
|
102
|
+
|
|
103
|
+
private def yard_type: (untyped type) -> untyped
|
|
104
|
+
|
|
105
|
+
private def emit_mcast_groups: () -> untyped
|
|
106
|
+
|
|
107
|
+
private def emit_subscription_methods: () -> untyped
|
|
108
|
+
|
|
109
|
+
private def emit_rbs_comment: (*untyped args) -> untyped
|
|
110
|
+
|
|
111
|
+
private def emit_yard_overload: (untyped signature) -> untyped
|
|
112
|
+
|
|
113
|
+
private def emit_yard_options: (untyped params, ?indentation: untyped) -> untyped
|
|
114
|
+
|
|
115
|
+
private def emit_yard_option: (untyped parameter, untyped name, untyped type, untyped description, ?indentation: untyped) -> untyped
|
|
116
|
+
|
|
117
|
+
private def emit_yard_attribute: (untyped name, untyped type, untyped description) -> untyped
|
|
118
|
+
|
|
119
|
+
private def emit_yard_param: (untyped name, untyped type, ?indentation: untyped) -> untyped
|
|
120
|
+
|
|
121
|
+
private def emit_yard_return: (untyped type, ?untyped description, ?indentation: untyped) -> untyped
|
|
122
|
+
|
|
123
|
+
private def emit_yard_see: (untyped object) -> untyped
|
|
124
|
+
|
|
125
|
+
private def emit_yard_yieldparam: (untyped name, untyped type, ?indentation: untyped) -> untyped
|
|
126
|
+
|
|
127
|
+
private def build_selector_plan: () -> untyped
|
|
128
|
+
|
|
129
|
+
private def require_selector: (untyped set, untyped selector) -> untyped
|
|
130
|
+
|
|
131
|
+
private def build_attribute_orders: () -> untyped
|
|
132
|
+
|
|
133
|
+
private def build_selector_sources: (untyped roots) -> untyped
|
|
134
|
+
|
|
135
|
+
private def validate_selector_values: () -> untyped
|
|
136
|
+
|
|
137
|
+
private def child_attribute_sets: (untyped type) -> untyped
|
|
138
|
+
|
|
139
|
+
private def attribute_by_name: (untyped set, untyped name) -> untyped
|
|
140
|
+
|
|
141
|
+
private def selector_source_literal: (untyped set, untyped selector) -> untyped
|
|
142
|
+
|
|
143
|
+
private def selector_bindings_literal: (untyped parent, untyped child) -> untyped
|
|
144
|
+
|
|
145
|
+
private def selector_value_literal: (untyped set, untyped selector, untyped format_value) -> untyped
|
|
146
|
+
|
|
147
|
+
private def to_datatype: (untyped type, untyped checks, ?owner: untyped) -> untyped
|
|
148
|
+
|
|
149
|
+
private def to_struct_member_datatype: (untyped type) -> untyped
|
|
150
|
+
|
|
151
|
+
private def to_checks: (untyped checks) -> untyped
|
|
152
|
+
|
|
153
|
+
private def to_check: (untyped check) -> untyped
|
|
154
|
+
|
|
155
|
+
private def check_message_value: (untyped check, untyped value) -> untyped
|
|
156
|
+
|
|
157
|
+
private def const_value_literal: (untyped value) -> untyped
|
|
158
|
+
|
|
159
|
+
private def integer_literal: (untyped value) -> untyped
|
|
160
|
+
|
|
161
|
+
private def mcast_group_value_literal: (untyped value) -> untyped
|
|
162
|
+
end
|
|
163
|
+
end
|