class BinaryStruct
Constants
- BIT_FORMATS
- ENDIAN_FORMATS
- ENDIAN_MODIFIERS
- MODIFIERS
- NIBBLE_FORMATS
- SIZES
- STRING_FORMATS
- VERSION
Public Class Methods
clear_structs_by_definition_cache()
click to toggle source
# File lib/binary_struct.rb, line 135 def self.clear_structs_by_definition_cache @@structs_by_definition.clear end
decode(data, definition)
click to toggle source
# File lib/binary_struct.rb, line 143 def self.decode(data, definition) struct_by_definition(definition).decode(data) end
encode(hash, definition)
click to toggle source
# File lib/binary_struct.rb, line 147 def self.encode(hash, definition) struct_by_definition(definition).encode(hash) end
new(definition = nil)
click to toggle source
# File lib/binary_struct.rb, line 49 def initialize(definition = nil) self.definition = definition unless definition.nil? end
sizeof(definition)
click to toggle source
# File lib/binary_struct.rb, line 139 def self.sizeof(definition) struct_by_definition(definition).size end
Private Class Methods
get_size(definition)
click to toggle source
# File lib/binary_struct.rb, line 201 def self.get_size(definition) size = 0 definition.each_slice(2) do |format, _| type, count = format[0, 1], format[1..-1] modifier, modcount = count[0, 1], count[1..-1] count = modcount if valid_definition_entry_modifier?(modifier) count = count.empty? ? 1 : count.to_i size += if BIT_FORMATS.include?(type) (count / 8.0).ceil elsif NIBBLE_FORMATS.include?(type) (count / 2.0).ceil else count * SIZES[type] end end size end
prep_decode(definition)
click to toggle source
# File lib/binary_struct.rb, line 220 def self.prep_decode(definition) formats = "" names = [] definition.each_slice(2) do |format, name| formats << format names << name end return formats, names end
struct_by_definition(definition)
click to toggle source
# File lib/binary_struct.rb, line 153 def self.struct_by_definition(definition) @@structs_by_definition[definition] ||= definition.kind_of?(self) ? definition : self.new(definition) end
valid_definition_entry_modifier?(modifier)
click to toggle source
# File lib/binary_struct.rb, line 189 def self.valid_definition_entry_modifier?(modifier) MODIFIERS.include? modifier end
validate_definition(definition)
click to toggle source
# File lib/binary_struct.rb, line 157 def self.validate_definition(definition) raise "definition must be an array of format/name pairs" if definition.empty? || definition.length % 2 != 0 definition.each_slice(2) do |format, _| type, count = format[0, 1], format[1..-1] modifier, modcount = count[0, 1], count[1..-1] validate_definition_entry_type(type) if valid_definition_entry_modifier?(modifier) validate_definition_endian_modifier(modifier, type) validate_definition_entry_count(modcount) else validate_definition_entry_count(count) end end end
validate_definition_endian_modifier(modifier, type)
click to toggle source
# File lib/binary_struct.rb, line 193 def self.validate_definition_endian_modifier(modifier, type) if ENDIAN_MODIFIERS.include? modifier raise "unsupported type attribute #{type} for endian modifier #{modifier}" unless ENDIAN_FORMATS.include? type return true end false end
validate_definition_entry_count(count)
click to toggle source
# File lib/binary_struct.rb, line 178 def self.validate_definition_entry_count(count) return true if count.empty? || count == '*' begin count = Integer(count) rescue raise "unsupported count: #{count}" end raise "unsupported count: #{count}" if count < 0 end
validate_definition_entry_type(type)
click to toggle source
# File lib/binary_struct.rb, line 172 def self.validate_definition_entry_type(type) raise "unrecognized format: #{type}" unless SIZES.has_key?(type) raise "unsupported format: #{type}" if SIZES[type].nil? return true end
Public Instance Methods
==(other)
click to toggle source
# File lib/binary_struct.rb, line 121 def ==(other) self.definition == other.definition end
decode(data, num = 1)
click to toggle source
# File lib/binary_struct.rb, line 73 def decode(data, num = 1) values = self.decode_to_array(data, num) return self.decoded_array_to_hash!(values) if num == 1 result = [] num.times { result << self.decoded_array_to_hash!(values) } return result end
decode_to_array(data, num = 1)
click to toggle source
# File lib/binary_struct.rb, line 82 def decode_to_array(data, num = 1) raise ArgumentError, "data cannot be nil" if data.nil? @decode_format, @decode_names = self.class.prep_decode(@definition) if @decode_format.nil? format = (num == 1) ? @decode_format : @decode_format * num return data.unpack(format) end
decoded_array_to_hash!(array)
click to toggle source
# File lib/binary_struct.rb, line 89 def decoded_array_to_hash!(array) hash = {} @decode_names.each do |k| v = array.shift next if k.nil? hash[k] = v end return hash end
definition()
click to toggle source
# File lib/binary_struct.rb, line 53 def definition @definition end
definition=(value)
click to toggle source
# File lib/binary_struct.rb, line 57 def definition=(value) if value.kind_of?(self.class) @definition = value.definition.dup else value = value.to_a.map(&:reverse).flatten if value.kind_of?(Hash) value = Array(value) self.class.validate_definition(value) @definition = value end @size = @decode_format = @decode_name = nil end
each(&block)
click to toggle source
# File lib/binary_struct.rb, line 125 def each(&block) self.definition.each_slice(2, &block) end
encode(hash)
click to toggle source
# File lib/binary_struct.rb, line 99 def encode(hash) return encode_hash(hash) unless hash.kind_of?(Array) data = "" hash.each { |h| data << self.encode_hash(h) } return data end
encode_hash(hash)
click to toggle source
# File lib/binary_struct.rb, line 107 def encode_hash(hash) data = "" @definition.each_slice(2) do |format, name| raise "member not found: #{name}" unless name.nil? || hash.has_key?(name) value = unless name.nil? hash[name] else STRING_FORMATS.include?(format[0, 1]) ? '0' : 0 end data << [value].pack(format) end return data end
size()
click to toggle source
# File lib/binary_struct.rb, line 69 def size @size ||= self.class.get_size(@definition) end