Class: BinData::DSLMixin::DSLBigAndLittleEndianHandler

Inherits:
Object
  • Object
show all
Defined in:
lib/bindata/dsl.rb

Overview

Handles the :big_and_little endian option. This option creates two subclasses, each handling :big or :little endian.

Class Method Summary collapse

Class Method Details

.class_with_endian(class_name, endian) ⇒ Object



334
335
336
337
338
339
340
# File 'lib/bindata/dsl.rb', line 334

def class_with_endian(class_name, endian)
  hints = {
    :endian => endian,
    :search_prefix => class_name.dsl_parser.search_prefix,
  }
  RegisteredClasses.lookup(class_name, hints)
end

.create_subclasses_with_endian(bnl_class) ⇒ Object



280
281
282
283
# File 'lib/bindata/dsl.rb', line 280

def create_subclasses_with_endian(bnl_class)
  instance_eval "class ::#{bnl_class}Be < ::#{bnl_class}; endian :big; end"
  instance_eval "class ::#{bnl_class}Le < ::#{bnl_class}; endian :little; end"
end

.delegate_field_creation(bnl_class) ⇒ Object



301
302
303
304
305
306
307
308
309
310
311
312
# File 'lib/bindata/dsl.rb', line 301

def delegate_field_creation(bnl_class)
  endian_classes = {
    :big    => class_with_endian(bnl_class, :big),
    :little => class_with_endian(bnl_class, :little),
  }

  parser = bnl_class.dsl_parser
  parser.define_singleton_method(:parse_and_append_field) do |*args, &block|
    endian_classes[:big].send(*args, &block)
    endian_classes[:little].send(*args, &block)
  end
end

.fixup_subclass_hierarchy(bnl_class) ⇒ Object



314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
# File 'lib/bindata/dsl.rb', line 314

def fixup_subclass_hierarchy(bnl_class)
  parent = bnl_class.superclass
  if obj_attribute(parent, :endian) == :big_and_little
    be_subclass = class_with_endian(bnl_class, :big)
    be_parent   = class_with_endian(parent, :big)
    be_fields   = obj_attribute(be_parent, :fields)

    le_subclass = class_with_endian(bnl_class, :little)
    le_parent   = class_with_endian(parent, :little)
    le_fields   = obj_attribute(le_parent, :fields)

    be_subclass.dsl_parser.define_singleton_method(:parent_fields) do
      be_fields
    end
    le_subclass.dsl_parser.define_singleton_method(:parent_fields) do
      le_fields
    end
  end
end

.handle(bnl_class) ⇒ Object



268
269
270
271
272
273
274
# File 'lib/bindata/dsl.rb', line 268

def handle(bnl_class)
  make_class_abstract(bnl_class)
  create_subclasses_with_endian(bnl_class)
  override_new_in_class(bnl_class)
  delegate_field_creation(bnl_class)
  fixup_subclass_hierarchy(bnl_class)
end

.make_class_abstract(bnl_class) ⇒ Object



276
277
278
# File 'lib/bindata/dsl.rb', line 276

def make_class_abstract(bnl_class)
  bnl_class.send(:unregister_self)
end

.obj_attribute(obj, attr, default = nil) ⇒ Object



342
343
344
345
346
347
348
349
# File 'lib/bindata/dsl.rb', line 342

def obj_attribute(obj, attr, default = nil)
  parser = obj.respond_to?(:dsl_parser) ? obj.dsl_parser : nil
  if parser and parser.respond_to?(attr)
    parser.send(attr)
  else
    default
  end
end

.override_new_in_class(bnl_class) ⇒ Object



285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
# File 'lib/bindata/dsl.rb', line 285

def override_new_in_class(bnl_class)
  endian_classes = {
    :big    => class_with_endian(bnl_class, :big),
    :little => class_with_endian(bnl_class, :little),
  }
  bnl_class.define_singleton_method(:new) do |*args|
    if self == bnl_class
      value, options, parent = arg_processor.separate_args(self, args)
      delegate = endian_classes[options[:endian]]
      return delegate.new(*args) if delegate
    end

    super(*args)
  end
end