class BinData::Struct
- calls to #read, #write, #num_bytes or #snapshot.
iffalse
, this object will not be included in any
[:onlyif
] Used to indicate a data object is optional.
Fields may have have extra parameters as listed below:
== Field Parameters
nested data objects.
endian of any numerics in this struct, or in any:endian
- Either :little or :big. This specifies the default
by name.
in #snapshot or #field_names but are still accessible
from the outside world. Hidden fields don’t appear:hide
- A list of the names of fields that are to be hidden
when instantiating it.
optional hash of parameters to pass to this field
type. Name is the name of this field. Params is an
params]. Type is a symbol representing a registered
Each element of the array is of the form [type, name,:fields
-
An array specifying the fields for this struct.
an object. These params are:
Parameters may be provided at initialisation to control the behaviour of
== Parameters
obj.field_names =># [“b”, “s”]
[:tuple, :s] ])
[:int16le, :b],
:fields => [ [:int32le, :a],
obj = BinData::Struct.new(:hide => :a,
end
int8 :z
int8 :y
int8 :x
class Tuple < BinData::Record
require ‘bindata’
A Struct is an ordered collection of named data objects.
- A list of the names of fields that are to be hidden
- Either :little or :big. This specifies the default
def _assign(val)
def _assign(val) clear assign_fields(as_snapshot(val)) end
def _do_num_bytes
def _do_num_bytes instantiate_all_objs sum_num_bytes_for_all_fields.ceil end
def _do_read(io)
def _do_read(io) instantiate_all_objs @field_objs.each { |f| f.do_read(io) if include_obj(f) } end
def _do_write(io)
def _do_write(io) instantiate_all_objs @field_objs.each { |f| f.do_write(io) if include_obj(f) } end
def _done_read
def _done_read @field_objs.each { |f| f.done_read if include_obj(f) } end
def _snapshot
def _snapshot snapshot = Snapshot.new field_names.each do |name| obj = find_obj_for_name(name) snapshot[name] = obj.snapshot if include_obj(obj) end snapshot end
def as_snapshot(val)
def as_snapshot(val) if val.class == Hash snapshot = Snapshot.new val.each_pair { |k,v| snapshot[k.to_s] = v unless v.nil? } snapshot elsif val.nil? Snapshot.new else val end end
def assign_fields(snapshot)
def assign_fields(snapshot) field_names(true).each do |name| obj = find_obj_for_name(name) if obj and snapshot.respond_to?(name) obj.assign(snapshot.__send__(name)) end end end
def clear #:nodoc:
def clear #:nodoc: @field_objs.each { |f| f.clear unless f.nil? } end
def clear? #:nodoc:
def clear? #:nodoc: @field_objs.inject(true) { |all_clear, f| all_clear and (f.nil? or f.clear?) } end
def debug_name_of(child) #:nodoc:
def debug_name_of(child) #:nodoc: field_name = @field_names[find_index_of(child)] "#{debug_name}.#{field_name}" end
def ensure_field_names_are_valid(field_names)
def ensure_field_names_are_valid(field_names) instance_methods = self.instance_methods.collect { |meth| meth.to_s } reserved_names = RESERVED field_names.each do |name| if instance_methods.include?(name) raise NameError.new("Rename field '#{name}' in #{self}, " + "as it shadows an existing method.", name) end if reserved_names.include?(name) raise NameError.new("Rename field '#{name}' in #{self}, " + "as it is a reserved name.", name) end if field_names.count(name) != 1 raise NameError.new("field '#{name}' in #{self}, " + "is defined multiple times.", name) end end end
def field_names(include_hidden = false)
object. +include_hidden+ specifies whether to include hidden names
Returns a list of the names of all fields accessible through this
def field_names(include_hidden = false) if include_hidden @field_names.dup else hidden = get_parameter(:hide) || [] @field_names - hidden end end
def find_index_of(obj)
def find_index_of(obj) @field_objs.index { |el| el.equal?(obj) } end
def find_obj_for_name(name)
def find_obj_for_name(name) field_name = name.to_s.chomp("=") index = @field_names.index(field_name) if index instantiate_obj_at(index) @field_objs[index] else nil end end
def hidden_field_names(hidden)
def hidden_field_names(hidden) (hidden || []).collect { |h| h.to_s } end
def include_obj(obj)
def include_obj(obj) not obj.has_parameter?(:onlyif) or obj.eval_parameter(:onlyif) end
def initialize(params = {}, parent = nil)
def initialize(params = {}, parent = nil) super(params, parent) @field_names = get_parameter(:fields).field_names @field_objs = [] end
def instantiate_all_objs
def instantiate_all_objs @field_names.each_index { |i| instantiate_obj_at(i) } end
def instantiate_obj_at(index)
def instantiate_obj_at(index) if @field_objs[index].nil? field = get_parameter(:fields)[index] @field_objs[index] = field.instantiate(self) end end
def invoke_field(obj, symbol, args)
def invoke_field(obj, symbol, args) name = symbol.to_s is_writer = (name[-1, 1] == "=") if is_writer obj.assign(*args) else obj end end
def method_missing(symbol, *args, &block) #:nodoc:
def method_missing(symbol, *args, &block) #:nodoc: obj = find_obj_for_name(symbol) if obj invoke_field(obj, symbol, args) else super end end
def offset_of(child) #:nodoc:
def offset_of(child) #:nodoc: instantiate_all_objs sum = sum_num_bytes_below_index(find_index_of(child)) child.do_num_bytes.is_a?(Integer) ? sum.ceil : sum.floor end
def respond_to?(symbol, include_private = false) #:nodoc:
def respond_to?(symbol, include_private = false) #:nodoc: super(symbol, include_private) || field_names(true).include?(symbol.to_s.chomp("=")) end
def sanitize_endian(params, sanitizer)
def sanitize_endian(params, sanitizer) if params.needs_sanitizing?(:endian) params[:endian] = sanitizer.create_sanitized_endian(params[:endian]) end end
def sanitize_fields(params, sanitizer)
def sanitize_fields(params, sanitizer) if params.needs_sanitizing?(:fields) fields = params[:fields] params[:fields] = sanitizer.create_sanitized_fields(params[:endian]) fields.each do |ftype, fname, fparams| params[:fields].add_field(ftype, fname, fparams) end field_names = sanitized_field_names(params[:fields]) ensure_field_names_are_valid(field_names) end end
def sanitize_hide(params, sanitizer)
def sanitize_hide(params, sanitizer) if params.needs_sanitizing?(:hide) and params.has_parameter?(:fields) field_names = sanitized_field_names(params[:fields]) hfield_names = hidden_field_names(params[:hide]) params[:hide] = (hfield_names & field_names) end end
def sanitize_parameters!(params, sanitizer) #:nodoc:
def sanitize_parameters!(params, sanitizer) #:nodoc: sanitize_endian(params, sanitizer) sanitize_fields(params, sanitizer) sanitize_hide(params, sanitizer) end
def sanitized_field_names(sanitized_fields)
def sanitized_field_names(sanitized_fields) sanitized_fields.field_names end
def sum_num_bytes_below_index(index)
def sum_num_bytes_below_index(index) sum = 0 (0...index).each do |i| obj = @field_objs[i] if include_obj(obj) nbytes = obj.do_num_bytes sum = (nbytes.is_a?(Integer) ? sum.ceil : sum) + nbytes end end sum end
def sum_num_bytes_for_all_fields
def sum_num_bytes_for_all_fields sum_num_bytes_below_index(@field_objs.length) end