lib/bindata/record.rb in bindata-1.3.1 vs lib/bindata/record.rb in bindata-1.4.0
- old
+ new
@@ -1,38 +1,52 @@
require 'bindata/dsl'
require 'bindata/sanitize'
require 'bindata/struct'
module BinData
+ # Extracts args for Records.
+ #
+ # Foo.new(:bar => "baz) is ambiguous as to whether :bar is a value or parameter.
+ #
+ # BaseArgExtractor always assumes :bar is parameter. This extractor correctly
+ # identifies it as value or parameter.
class RecordArgExtractor
- def self.extract(the_class, the_args)
- value, parameters, parent = BaseArgExtractor.extract(the_class, the_args)
+ class << self
+ def extract(the_class, the_args)
+ value, parameters, parent = BaseArgExtractor.extract(the_class, the_args)
- if value.nil? and parameters.length > 0
- if field_names_in_parameters(the_class, parameters).length > 0
+ if parameters_is_value?(the_class, value, parameters)
value = parameters
- parameters = nil
+ parameters = {}
end
+
+ [value, parameters, parent]
end
- [value, parameters, parent]
- end
+ def parameters_is_value?(the_class, value, parameters)
+ if value.nil? and parameters.length > 0
+ field_names_in_parameters?(the_class, parameters)
+ else
+ false
+ end
+ end
- def self.field_names_in_parameters(the_class, parameters)
- field_names = the_class.fields.field_names.collect { |k| k.to_s }
- param_keys = parameters.keys.collect { |k| k.to_s }
+ def field_names_in_parameters?(the_class, parameters)
+ field_names = the_class.fields.field_names
+ param_keys = parameters.keys
- (field_names & param_keys)
+ (field_names & param_keys).length > 0
+ end
end
end
# A Record is a declarative wrapper around Struct.
#
# require 'bindata'
#
# class SomeDataType < BinData::Record
- # hide 'a'
+ # hide :a
#
# int32le :a
# int16le :b
# struct :s do
# int8 :x
@@ -43,71 +57,51 @@
#
# obj = SomeDataType.new
# obj.field_names =># ["b", "s"]
# obj.s.field_names =># ["x", "y", "z"]
#
- #
- # == Parameters
- #
- # Parameters may be provided at initialisation to control the behaviour of
- # an object. These params are:
- #
- # <tt>:fields</tt>:: An array specifying the fields for this struct.
- # Each element of the array is of the form [type, name,
- # params]. Type is a symbol representing a registered
- # type. Name is the name of this field. Params is an
- # optional hash of parameters to pass to this field
- # when instantiating it.
- # <tt>:hide</tt>:: A list of the names of fields that are to be hidden
- # from the outside world. Hidden fields don't appear
- # in #snapshot or #field_names but are still accessible
- # by name.
- # <tt>:endian</tt>:: Either :little or :big. This specifies the default
- # endian of any numerics in this struct, or in any
- # nested data objects.
class Record < BinData::Struct
include DSLMixin
- register_subclasses
- dsl_parser :multiple_fields, :optional_fieldnames, :sanitize_fields, :hidden_fields
+ unregister_self
+ dsl_parser :struct
class << self
def arg_extractor
RecordArgExtractor
end
- def sanitize_parameters!(params, sanitizer) #:nodoc:
- params[:fields] = fields
- params[:endian] = endian unless endian.nil?
- params[:hide] = hide unless hide.empty?
+ def sanitize_parameters!(params) #:nodoc:
+ params.merge!(dsl_params)
- super(params, sanitizer)
+ super(params)
define_field_accessors(params[:fields].fields)
end
# Defines accessor methods to avoid the overhead of going through
# Struct#method_missing. This is purely a speed optimisation.
# Removing this method will not have any effect on correctness.
def define_field_accessors(fields) #:nodoc:
unless method_defined?(:bindata_defined_accessors_for_fields?)
fields.each_with_index do |field, i|
- if field.name
- define_field_accessors_for(field.name, i)
+ name = field.name_as_sym
+ if name
+ define_field_accessors_for(name, i)
end
end
define_method(:bindata_defined_accessors_for_fields?) { true }
end
end
def define_field_accessors_for(name, index)
- define_method(name.to_sym) do
+ define_method(name) do
instantiate_obj_at(index) unless @field_objs[index]
@field_objs[index]
end
- define_method((name + "=").to_sym) do |*vals|
+ define_method(name.to_s + "=") do |*vals|
instantiate_obj_at(index) unless @field_objs[index]
@field_objs[index].assign(*vals)
end
end
end