lib/bindata/record.rb in bindata-1.1.0 vs lib/bindata/record.rb in bindata-1.2.0
- old
+ new
@@ -1,29 +1,29 @@
+require 'bindata/dsl'
require 'bindata/sanitize'
require 'bindata/struct'
module BinData
# A Record is a declarative wrapper around Struct.
#
# require 'bindata'
#
- # class Tuple < BinData::Record
- # int8 :x
- # int8 :y
- # int8 :z
- # end
- #
# class SomeDataType < BinData::Record
# hide 'a'
#
# int32le :a
# int16le :b
- # tuple :s
+ # struct :s do
+ # int8 :x
+ # int8 :y
+ # int8 :z
+ # end
# end
#
# 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
@@ -41,109 +41,21 @@
# 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
- class << self
+ register_subclasses
+ dsl_parser :multiple_fields, :optional_fieldnames, :sanitize_fields, :hidden_fields
- def inherited(subclass) #:nodoc:
- # Register the names of all subclasses of this class.
- register(subclass.name, subclass)
- end
-
- def endian(endian = nil)
- @endian ||= default_endian
- if [:little, :big].include?(endian)
- @endian = endian
- elsif endian != nil
- raise ArgumentError,
- "unknown value for endian '#{endian}' in #{self}", caller(1)
- end
- @endian
- end
-
- def hide(*args)
- @hide ||= default_hide
- @hide.concat(args.collect { |name| name.to_s })
- @hide
- end
-
- def fields #:nodoc:
- @fields ||= default_fields
- end
-
- def method_missing(symbol, *args) #:nodoc:
- name, params = args
-
- if name.is_a?(Hash)
- params = name
- name = nil
- end
-
- type = symbol
- name = name.to_s
- params ||= {}
-
- append_field(type, name, params)
- end
-
+ class << self
def sanitize_parameters!(params, sanitizer) #:nodoc:
params[:fields] = fields
params[:endian] = endian unless endian.nil?
params[:hide] = hide unless hide.empty?
super(params, sanitizer)
- end
-
- #-------------
- private
-
- def parent_record
- ancestors[1..-1].find { |cls|
- cls.ancestors[1..-1].include?(BinData::Record)
- }
- end
-
- def default_endian
- rec = parent_record
- rec ? rec.endian : nil
- end
-
- def default_hide
- rec = parent_record
- rec ? rec.hide.dup : []
- end
-
- def default_fields
- rec = parent_record
- if rec
- Sanitizer.new.clone_sanitized_fields(rec.fields)
- else
- Sanitizer.new.create_sanitized_fields
- end
- end
-
- def append_field(type, name, params)
- ensure_valid_name(name)
-
- fields.add_field(type, name, params, endian)
- rescue UnknownTypeError => err
- raise TypeError, "unknown type '#{err.message}' for #{self}", caller(2)
- end
-
- def ensure_valid_name(name)
- if fields.field_names.include?(name)
- raise SyntaxError, "duplicate field '#{name}' in #{self}", caller(3)
- end
- if self.instance_methods.collect { |meth| meth.to_s }.include?(name)
- raise NameError.new("", name),
- "field '#{name}' shadows an existing method in #{self}", caller(3)
- end
- if self::RESERVED.include?(name)
- raise NameError.new("", name),
- "field '#{name}' is a reserved name in #{self}", caller(3)
- end
end
end
end
end