bindata 2.0.0 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of bindata might be problematic. Click here for more details.

@@ -51,32 +51,18 @@ module BinData
51
51
  # <tt>:type</tt>:: The single type inside the buffer. Use a struct if
52
52
  # multiple fields are required.
53
53
  class Buffer < BinData::Base
54
- include DSLMixin
54
+ extend DSLMixin
55
55
 
56
- dsl_parser :buffer
56
+ dsl_parser :buffer
57
+ arg_processor :buffer
57
58
 
58
59
  mandatory_parameters :length, :type
59
60
 
60
- class << self
61
- def arg_extractor
62
- MultiFieldArgExtractor
63
- end
64
-
65
- def sanitize_parameters!(params) #:nodoc:
66
- params.merge!(dsl_params)
67
-
68
- if params.needs_sanitizing?(:type)
69
- el_type, el_params = params[:type]
70
- params[:type] = params.create_sanitized_object_prototype(el_type, el_params)
71
- end
72
- end
73
- end
74
-
75
61
  def initialize_instance
76
62
  @type = get_parameter(:type).instantiate(nil, self)
77
63
  end
78
64
 
79
- def clear? #:nodoc:
65
+ def clear?
80
66
  @type.clear?
81
67
  end
82
68
 
@@ -116,4 +102,19 @@ module BinData
116
102
  eval_parameter(:length)
117
103
  end
118
104
  end
105
+
106
+ class BufferArgProcessor < BaseArgProcessor
107
+ include MultiFieldArgSeparator
108
+
109
+ def sanitize_parameters!(obj_class, params)
110
+ params.merge!(obj_class.dsl_params)
111
+
112
+ params.must_be_integer(:length)
113
+
114
+ if params.needs_sanitizing?(:type)
115
+ el_type, el_params = params[:type]
116
+ params[:type] = params.create_sanitized_object_prototype(el_type, el_params)
117
+ end
118
+ end
119
+ end
119
120
  end
@@ -58,54 +58,14 @@ module BinData
58
58
  # selection to the current selection whenever the
59
59
  # selection changes. Default is false.
60
60
  class Choice < BinData::Base
61
- include DSLMixin
61
+ extend DSLMixin
62
62
 
63
- dsl_parser :choice
63
+ dsl_parser :choice
64
+ arg_processor :choice
64
65
 
65
66
  mandatory_parameters :choices, :selection
66
67
  optional_parameter :copy_on_change
67
68
 
68
- class << self
69
-
70
- def sanitize_parameters!(params) #:nodoc:
71
- params.merge!(dsl_params)
72
-
73
- if params.needs_sanitizing?(:choices)
74
- choices = choices_as_hash(params[:choices])
75
- ensure_valid_keys(choices)
76
- params[:choices] = params.create_sanitized_choices(choices)
77
- end
78
- end
79
-
80
- #-------------
81
- private
82
-
83
- def choices_as_hash(choices)
84
- if choices.respond_to?(:to_ary)
85
- key_array_by_index(choices.to_ary)
86
- else
87
- choices
88
- end
89
- end
90
-
91
- def key_array_by_index(array)
92
- result = {}
93
- array.each_with_index do |el, i|
94
- result[i] = el unless el.nil?
95
- end
96
- result
97
- end
98
-
99
- def ensure_valid_keys(choices)
100
- if choices.has_key?(nil)
101
- raise ArgumentError, ":choices hash may not have nil key"
102
- end
103
- if choices.keys.detect { |key| key.is_a?(Symbol) and key != :default }
104
- raise ArgumentError, ":choices hash may not have symbols for keys"
105
- end
106
- end
107
- end
108
-
109
69
  def initialize_shared_instance
110
70
  extend CopyOnChangePlugin if eval_parameter(:copy_on_change) == true
111
71
  super
@@ -125,40 +85,24 @@ module BinData
125
85
  selection
126
86
  end
127
87
 
128
- def clear? #:nodoc:
129
- current_choice.clear?
130
- end
131
-
132
- def assign(val)
133
- current_choice.assign(val)
134
- end
135
-
136
- def snapshot
137
- current_choice.snapshot
88
+ def safe_respond_to?(symbol, include_private = false) #:nodoc:
89
+ base_respond_to?(symbol, include_private)
138
90
  end
139
91
 
140
92
  def respond_to?(symbol, include_private = false) #:nodoc:
141
93
  current_choice.respond_to?(symbol, include_private) || super
142
94
  end
143
95
 
144
- def safe_respond_to?(symbol, include_private = false) #:nodoc:
145
- base_respond_to?(symbol, include_private)
146
- end
147
-
148
96
  def method_missing(symbol, *args, &block) #:nodoc:
149
97
  current_choice.__send__(symbol, *args, &block)
150
98
  end
151
99
 
152
- def do_read(io) #:nodoc:
153
- current_choice.do_read(io)
154
- end
155
-
156
- def do_write(io) #:nodoc:
157
- current_choice.do_write(io)
158
- end
159
-
160
- def do_num_bytes #:nodoc:
161
- current_choice.do_num_bytes
100
+ %w(clear? assign snapshot do_read do_write do_num_bytes).each do |m|
101
+ self.module_eval <<-END
102
+ def #{m}(*args)
103
+ current_choice.#{m}(*args)
104
+ end
105
+ END
162
106
  end
163
107
 
164
108
  #---------------
@@ -178,6 +122,46 @@ module BinData
178
122
  end
179
123
  end
180
124
 
125
+ class ChoiceArgProcessor < BaseArgProcessor
126
+ def sanitize_parameters!(obj_class, params) #:nodoc:
127
+ params.merge!(obj_class.dsl_params)
128
+
129
+ if params.needs_sanitizing?(:choices)
130
+ choices = choices_as_hash(params[:choices])
131
+ ensure_valid_keys(choices)
132
+ params[:choices] = params.create_sanitized_choices(choices)
133
+ end
134
+ end
135
+
136
+ #-------------
137
+ private
138
+
139
+ def choices_as_hash(choices)
140
+ if choices.respond_to?(:to_ary)
141
+ key_array_by_index(choices.to_ary)
142
+ else
143
+ choices
144
+ end
145
+ end
146
+
147
+ def key_array_by_index(array)
148
+ result = {}
149
+ array.each_with_index do |el, i|
150
+ result[i] = el unless el.nil?
151
+ end
152
+ result
153
+ end
154
+
155
+ def ensure_valid_keys(choices)
156
+ if choices.has_key?(nil)
157
+ raise ArgumentError, ":choices hash may not have nil key"
158
+ end
159
+ if choices.keys.detect { |key| key.is_a?(Symbol) and key != :default }
160
+ raise ArgumentError, ":choices hash may not have symbols for keys"
161
+ end
162
+ end
163
+ end
164
+
181
165
  # Logic for the :copy_on_change parameter
182
166
  module CopyOnChangePlugin
183
167
  def current_choice
@@ -5,60 +5,52 @@ module BinData
5
5
  #
6
6
  # BaseArgExtractor always assumes :bar is parameter. This extractor correctly
7
7
  # identifies it as value or parameter.
8
- class MultiFieldArgExtractor
9
- class << self
10
- def extract(the_class, the_args)
11
- value, parameters, parent = BaseArgExtractor.extract(the_class, the_args)
12
-
13
- if parameters_is_value?(the_class, value, parameters)
14
- value = parameters
15
- parameters = {}
16
- end
8
+ module MultiFieldArgSeparator
9
+ def separate_args(obj_class, obj_args)
10
+ value, parameters, parent = super(obj_class, obj_args)
17
11
 
18
- [value, parameters, parent]
12
+ if parameters_is_value?(obj_class, value, parameters)
13
+ value = parameters
14
+ parameters = {}
19
15
  end
20
16
 
21
- def parameters_is_value?(the_class, value, parameters)
22
- if value.nil? and parameters.length > 0
23
- field_names_in_parameters?(the_class, parameters)
24
- else
25
- false
26
- end
17
+ [value, parameters, parent]
18
+ end
19
+
20
+ def parameters_is_value?(obj_class, value, parameters)
21
+ if value.nil? and parameters.length > 0
22
+ field_names_in_parameters?(obj_class, parameters)
23
+ else
24
+ false
27
25
  end
26
+ end
28
27
 
29
- def field_names_in_parameters?(the_class, parameters)
30
- field_names = the_class.fields.field_names
31
- param_keys = parameters.keys
28
+ def field_names_in_parameters?(obj_class, parameters)
29
+ field_names = obj_class.fields.field_names
30
+ param_keys = parameters.keys
32
31
 
33
- (field_names & param_keys).length > 0
34
- end
32
+ (field_names & param_keys).length > 0
35
33
  end
36
34
  end
37
35
 
36
+ # BinData classes that are part of the DSL must be extended by this.
38
37
  module DSLMixin
39
- def self.included(base) #:nodoc:
40
- base.extend ClassMethods
41
- end
42
-
43
- module ClassMethods
44
-
45
- def dsl_parser(parser_type = nil)
46
- unless defined? @dsl_parser
47
- parser_type = superclass.dsl_parser.parser_type if parser_type.nil?
48
- @dsl_parser = DSLParser.new(self, parser_type)
49
- end
50
- @dsl_parser
51
- end
52
-
53
- def method_missing(symbol, *args, &block) #:nodoc:
54
- dsl_parser.__send__(symbol, *args, &block)
38
+ def dsl_parser(parser_type = nil)
39
+ unless defined? @dsl_parser
40
+ parser_type = superclass.dsl_parser.parser_type if parser_type.nil?
41
+ @dsl_parser = DSLParser.new(self, parser_type)
55
42
  end
43
+ @dsl_parser
44
+ end
56
45
 
57
- # Assert object is not an array or string.
58
- def to_ary; nil; end
59
- def to_str; nil; end
46
+ def method_missing(symbol, *args, &block) #:nodoc:
47
+ dsl_parser.__send__(symbol, *args, &block)
60
48
  end
61
49
 
50
+ # Assert object is not an array or string.
51
+ def to_ary; nil; end
52
+ def to_str; nil; end
53
+
62
54
  # A DSLParser parses and accumulates field definitions of the form
63
55
  #
64
56
  # type name, params
@@ -70,21 +62,25 @@ module BinData
70
62
  #
71
63
  class DSLParser
72
64
  def initialize(the_class, parser_type)
73
- @the_class = the_class
74
- @parser_type = parser_type
75
- @endian = parent_attribute(:endian, nil)
65
+ raise "unknown parser type #{parser_type}" unless parser_abilities[parser_type]
66
+
67
+ @the_class = the_class
68
+ @parser_type = parser_type
69
+ @validator = DSLFieldValidator.new(the_class, self)
70
+ @endian_handler = DSLBigAndLittleEndianHandler.new(the_class)
71
+ @endian = nil
76
72
  end
77
73
 
78
74
  attr_reader :parser_type
79
75
 
80
76
  def endian(endian = nil)
81
- if endian.nil?
82
- @endian
83
- elsif endian == :big or endian == :little
84
- @endian = endian
85
- else
86
- dsl_raise ArgumentError, "unknown value for endian '#{endian}'"
77
+ if endian
78
+ set_endian(endian)
79
+ elsif @endian.nil?
80
+ pendian = parent_attribute(:endian, nil)
81
+ set_endian(pendian) if pendian
87
82
  end
83
+ @endian
88
84
  end
89
85
 
90
86
  def hide(*args)
@@ -102,7 +98,7 @@ module BinData
102
98
 
103
99
  def fields
104
100
  unless defined? @fields
105
- fields = parent_attribute(:fields, nil)
101
+ fields = @endian_handler.ancestor_fields || parent_attribute(:fields)
106
102
  @fields = SanitizedFields.new(endian)
107
103
  @fields.copy_fields(fields) if fields
108
104
  end
@@ -111,62 +107,217 @@ module BinData
111
107
  end
112
108
 
113
109
  def dsl_params
114
- case @parser_type
115
- when :struct
116
- to_struct_params
117
- when :array
118
- to_array_params
119
- when :buffer
120
- to_array_params
121
- when :choice
122
- to_choice_params
123
- when :primitive
124
- to_struct_params
110
+ send(parser_abilities[@parser_type].at(0))
111
+ end
112
+
113
+ def method_missing(*args, &block)
114
+ if endian == :big_and_little
115
+ @endian_handler.forward_field_definition(*args, &block)
125
116
  else
126
- raise "unknown parser type #{@parser_type}"
117
+ parse_and_append_field(*args, &block)
118
+ end
119
+ end
120
+
121
+ #-------------
122
+ private
123
+
124
+ def parser_abilities
125
+ @abilities ||= {
126
+ :struct => [:to_struct_params, [:multiple_fields, :optional_fieldnames, :hidden_fields]],
127
+ :array => [:to_array_params, [:multiple_fields, :optional_fieldnames]],
128
+ :buffer => [:to_array_params, [:multiple_fields, :optional_fieldnames]],
129
+ :choice => [:to_choice_params, [:multiple_fields, :all_or_none_fieldnames, :fieldnames_are_values]],
130
+ :primitive => [:to_struct_params, [:multiple_fields, :optional_fieldnames]]
131
+ }
132
+ end
133
+
134
+ def option?(opt)
135
+ parser_abilities[@parser_type].at(1).include?(opt)
136
+ end
137
+
138
+ def set_endian(endian)
139
+ if has_fields?
140
+ dsl_raise SyntaxError, "endian must not be called after defining fields"
127
141
  end
142
+ if not valid_endian?(endian)
143
+ dsl_raise ArgumentError, "unknown value for endian '#{endian}'"
144
+ end
145
+
146
+ if endian == :big_and_little
147
+ @endian_handler.prepare_subclasses
148
+ end
149
+
150
+ @endian = endian
128
151
  end
129
152
 
130
- def method_missing(symbol, *args, &block) #:nodoc:
131
- type = symbol
132
- name = name_from_field_declaration(args)
133
- params = params_from_field_declaration(type, args, &block)
153
+ def has_fields?
154
+ @fields && @fields.length > 0
155
+ end
134
156
 
135
- append_field(type, name, params)
157
+ def valid_endian?(endian)
158
+ [:big, :little, :big_and_little].include?(endian)
159
+ end
160
+
161
+ def parent_attribute(attr, default = nil)
162
+ parent = @the_class.superclass
163
+ parser = parent.respond_to?(:dsl_parser) ? parent.dsl_parser : nil
164
+ if parser and parser.respond_to?(attr)
165
+ parser.send(attr)
166
+ else
167
+ default
168
+ end
169
+ end
170
+
171
+ def parse_and_append_field(*args, &block)
172
+ parser = DSLFieldParser.new(endian, *args, &block)
173
+ begin
174
+ @validator.validate_field(parser.name)
175
+ append_field(parser.type, parser.name, parser.params)
176
+ rescue Exception => err
177
+ dsl_raise err.class, err.message
178
+ end
179
+ end
180
+
181
+ def append_field(type, name, params)
182
+ fields.add_field(type, name, params)
183
+ rescue BinData::UnRegisteredTypeError => err
184
+ raise TypeError, "unknown type '#{err.message}'"
185
+ end
186
+
187
+ def dsl_raise(exception, message)
188
+ backtrace = caller
189
+ backtrace.shift while %r{bindata/dsl.rb} =~ backtrace.first
190
+
191
+ raise exception, message + " in #{@the_class}", backtrace
192
+ end
193
+
194
+ def to_array_params
195
+ case fields.length
196
+ when 0
197
+ {}
198
+ when 1
199
+ {:type => fields[0].prototype}
200
+ else
201
+ {:type => [:struct, to_struct_params]}
202
+ end
203
+ end
204
+
205
+ def to_choice_params
206
+ if fields.length == 0
207
+ {}
208
+ elsif fields.all_field_names_blank?
209
+ {:choices => fields.collect { |f| f.prototype }}
210
+ else
211
+ choices = {}
212
+ fields.each { |f| choices[f.name] = f.prototype }
213
+ {:choices => choices}
214
+ end
215
+ end
216
+
217
+ def to_struct_params
218
+ result = {:fields => fields}
219
+ if not endian.nil?
220
+ result[:endian] = endian
221
+ end
222
+ if option?(:hidden_fields) and not hide.empty?
223
+ result[:hide] = hide
224
+ end
225
+
226
+ result
227
+ end
228
+ end
229
+
230
+ # Handles the :big_and_little endian option.
231
+ # This option creates two subclasses, each handling
232
+ # :big or :little endian.
233
+ class DSLBigAndLittleEndianHandler
234
+ def initialize(the_class)
235
+ @the_class = the_class
236
+ end
237
+
238
+ def prepare_subclasses
239
+ create_subclasses_with_endian
240
+ make_class_abstract
241
+ override_new_in_class
242
+ end
243
+
244
+ def forward_field_definition(*args, &block)
245
+ class_with_endian(@the_class, :big).send(*args, &block)
246
+ class_with_endian(@the_class, :little).send(*args, &block)
247
+ end
248
+
249
+ def ancestor_fields
250
+ if subclass_of_big_and_little_endian?
251
+ pparent = @the_class.superclass.superclass
252
+ ancestor_with_endian = class_with_endian(pparent, @the_class.endian)
253
+ obj_attribute(ancestor_with_endian, :fields)
254
+ else
255
+ nil
256
+ end
136
257
  end
137
258
 
138
259
  #-------------
139
260
  private
140
261
 
141
- def option?(opt)
142
- options.include?(opt)
143
- end
144
-
145
- def options
146
- case @parser_type
147
- when :struct
148
- [:multiple_fields, :optional_fieldnames, :hidden_fields]
149
- when :array
150
- [:multiple_fields, :optional_fieldnames]
151
- when :buffer
152
- [:multiple_fields, :optional_fieldnames]
153
- when :choice
154
- [:multiple_fields, :all_or_none_fieldnames, :fieldnames_are_values]
155
- when :primitive
156
- [:multiple_fields, :optional_fieldnames]
157
- else
158
- raise "unknown parser type #{parser_type}"
262
+ def create_subclasses_with_endian
263
+ instance_eval "class ::#{@the_class}Be < ::#{@the_class}; endian :big; end"
264
+ instance_eval "class ::#{@the_class}Le < ::#{@the_class}; endian :little; end"
265
+ end
266
+
267
+ def make_class_abstract
268
+ @the_class.send(:unregister_self)
269
+ end
270
+
271
+ def override_new_in_class
272
+ saved_class = @the_class
273
+ endian_classes = {
274
+ :big => class_with_endian(saved_class, :big),
275
+ :little => class_with_endian(saved_class, :little),
276
+ }
277
+ @the_class.define_singleton_method(:new) do |*args|
278
+ if self == saved_class
279
+ value, options, parent = arg_processor.separate_args(self, args)
280
+ delegate = endian_classes[options[:endian]]
281
+ return delegate.new(*args) if delegate
282
+ end
283
+
284
+ super(*args)
159
285
  end
160
286
  end
161
287
 
162
- def parent_attribute(attr, default = nil)
163
- parent = @the_class.superclass.respond_to?(:dsl_parser) ? @the_class.superclass.dsl_parser : nil
164
- if parent and parent.respond_to?(attr)
165
- parent.send(attr)
288
+ def subclass_of_big_and_little_endian?
289
+ parent = @the_class.superclass
290
+ pparent = parent.superclass
291
+
292
+ obj_attribute(parent, :endian) == :big_and_little and
293
+ obj_attribute(pparent, :endian) == :big_and_little and
294
+ [:big, :little].include?(@the_class.endian)
295
+ end
296
+
297
+ def class_with_endian(class_name, endian)
298
+ RegisteredClasses.lookup(class_name, endian)
299
+ end
300
+
301
+ def obj_attribute(obj, attr, default = nil)
302
+ parser = obj.respond_to?(:dsl_parser) ? obj.dsl_parser : nil
303
+ if parser and parser.respond_to?(attr)
304
+ parser.send(attr)
166
305
  else
167
306
  default
168
307
  end
169
308
  end
309
+ end
310
+
311
+ # Extracts the details from a field declaration.
312
+ class DSLFieldParser
313
+ def initialize(endian, symbol, *args, &block)
314
+ @endian = endian
315
+ @type = symbol
316
+ @name = name_from_field_declaration(args)
317
+ @params = params_from_field_declaration(args, &block)
318
+ end
319
+
320
+ attr_reader :type, :name, :params
170
321
 
171
322
  def name_from_field_declaration(args)
172
323
  name, params = args
@@ -177,11 +328,11 @@ module BinData
177
328
  end
178
329
  end
179
330
 
180
- def params_from_field_declaration(type, args, &block)
331
+ def params_from_field_declaration(args, &block)
181
332
  params = params_from_args(args)
182
333
 
183
334
  if block_given?
184
- params.merge(params_from_block(type, &block))
335
+ params.merge(params_from_block(&block))
185
336
  else
186
337
  params
187
338
  end
@@ -194,7 +345,7 @@ module BinData
194
345
  params || {}
195
346
  end
196
347
 
197
- def params_from_block(type, &block)
348
+ def params_from_block(&block)
198
349
  bindata_classes = {
199
350
  :array => BinData::Array,
200
351
  :buffer => BinData::Buffer,
@@ -202,9 +353,9 @@ module BinData
202
353
  :struct => BinData::Struct
203
354
  }
204
355
 
205
- if bindata_classes.include?(type)
206
- parser = DSLParser.new(bindata_classes[type], type)
207
- parser.endian(endian)
356
+ if bindata_classes.include?(@type)
357
+ parser = DSLParser.new(bindata_classes[@type], @type)
358
+ parser.endian(@endian)
208
359
  parser.instance_eval(&block)
209
360
 
210
361
  parser.dsl_params
@@ -212,61 +363,51 @@ module BinData
212
363
  {}
213
364
  end
214
365
  end
366
+ end
215
367
 
216
- def append_field(type, name, params)
217
- ensure_valid_field(name)
218
-
219
- fields.add_field(type, name, params)
220
- rescue ArgumentError => err
221
- dsl_raise ArgumentError, err.message
222
- rescue UnRegisteredTypeError => err
223
- dsl_raise TypeError, "unknown type '#{err.message}'"
368
+ # Validates a field defined in a DSLMixin.
369
+ class DSLFieldValidator
370
+ def initialize(the_class, parser)
371
+ @the_class = the_class
372
+ @dsl_parser = parser
224
373
  end
225
374
 
226
- def ensure_valid_field(field_name)
227
- if too_many_fields?
228
- dsl_raise SyntaxError, "attempting to wrap more than one type"
229
- end
230
-
231
- if must_not_have_a_name_failed?(field_name)
232
- dsl_raise SyntaxError, "field must not have a name"
375
+ def validate_field(name)
376
+ if must_not_have_a_name_failed?(name)
377
+ raise SyntaxError, "field must not have a name"
233
378
  end
234
379
 
235
- if all_or_none_names_failed?(field_name)
236
- dsl_raise SyntaxError, "fields must either all have names, or none must have names"
380
+ if all_or_none_names_failed?(name)
381
+ raise SyntaxError, "fields must either all have names, or none must have names"
237
382
  end
238
383
 
239
- if must_have_a_name_failed?(field_name)
240
- dsl_raise SyntaxError, "field must have a name"
384
+ if must_have_a_name_failed?(name)
385
+ raise SyntaxError, "field must have a name"
241
386
  end
242
387
 
243
- ensure_valid_name(field_name)
388
+ ensure_valid_name(name)
244
389
  end
245
390
 
246
391
  def ensure_valid_name(name)
247
392
  if name and not option?(:fieldnames_are_values)
248
393
  if malformed_name?(name)
249
- dsl_raise NameError.new("", name), "field '#{name}' is an illegal fieldname"
394
+ raise NameError.new("", name), "field '#{name}' is an illegal fieldname"
250
395
  end
251
396
 
252
397
  if duplicate_name?(name)
253
- dsl_raise SyntaxError, "duplicate field '#{name}'"
398
+ raise SyntaxError, "duplicate field '#{name}'"
254
399
  end
255
400
 
256
401
  if name_shadows_method?(name)
257
- dsl_raise NameError.new("", name), "field '#{name}' shadows an existing method"
402
+ raise NameError.new("", name), "field '#{name}' shadows an existing method"
258
403
  end
259
404
 
260
405
  if name_is_reserved?(name)
261
- dsl_raise NameError.new("", name), "field '#{name}' is a reserved name"
406
+ raise NameError.new("", name), "field '#{name}' is a reserved name"
262
407
  end
263
408
  end
264
409
  end
265
410
 
266
- def too_many_fields?
267
- option?(:only_one_field) and not fields.empty?
268
- end
269
-
270
411
  def must_not_have_a_name_failed?(name)
271
412
  option?(:no_fieldnames) and name != nil
272
413
  end
@@ -302,46 +443,12 @@ module BinData
302
443
  BinData::Struct::RESERVED.include?(name.to_sym)
303
444
  end
304
445
 
305
- def dsl_raise(exception, message)
306
- backtrace = caller
307
- backtrace.shift while %r{bindata/dsl.rb} =~ backtrace.first
308
-
309
- raise exception, message + " in #{@the_class}", backtrace
310
- end
311
-
312
- def to_array_params
313
- case fields.length
314
- when 0
315
- {}
316
- when 1
317
- {:type => fields[0].prototype}
318
- else
319
- {:type => [:struct, to_struct_params]}
320
- end
321
- end
322
-
323
- def to_choice_params
324
- if fields.length == 0
325
- {}
326
- elsif fields.all_field_names_blank?
327
- {:choices => fields.collect { |f| f.prototype }}
328
- else
329
- choices = {}
330
- fields.each { |f| choices[f.name] = f.prototype }
331
- {:choices => choices}
332
- end
446
+ def fields
447
+ @dsl_parser.fields
333
448
  end
334
449
 
335
- def to_struct_params
336
- result = {:fields => fields}
337
- if not endian.nil?
338
- result[:endian] = endian
339
- end
340
- if option?(:hidden_fields) and not hide.empty?
341
- result[:hide] = hide
342
- end
343
-
344
- result
450
+ def option?(opt)
451
+ @dsl_parser.send(:option?, opt)
345
452
  end
346
453
  end
347
454
  end