class Mingle::BinCodec::MingleBinCodec
Constants
- BYTE_ORDER
Public Class Methods
new()
click to toggle source
# File lib/mingle/bincodec.rb, line 37 def initialize @conv = Io::BinaryConverter.new( :order => BYTE_ORDER ) end
Public Instance Methods
as_buffer( obj )
click to toggle source
# File lib/mingle/bincodec.rb, line 201 def as_buffer( obj ) not_nil( obj, :obj ) obj.is_a?( MingleStruct ) or codec_raise( "Not a struct: #{obj}" ) buf = RubyVersions.when_19x( StringIO.new ) do |io| io.set_encoding( "binary" ) end wr = Io::BinaryWriter.new( :order => BYTE_ORDER, :io => buf ) append_struct( wr, obj ) buf.string end
from_buffer( buf )
click to toggle source
# File lib/mingle/bincodec.rb, line 427 def from_buffer( buf ) validate_from_buffer_args( buf ) scanner = Io::BinaryReader.new( :order => BYTE_ORDER, :io => StringIO.new( buf ) ) if ( res = read_value( scanner ) ).is_a?( MingleStruct ) res else raise "Decode res wasn't a struct; got #{res.class}" end end
Private Instance Methods
append_boolean( wr, val )
click to toggle source
# File lib/mingle/bincodec.rb, line 62 def append_boolean( wr, val ) append_type_code( wr, TYPE_CODE_BOOLEAN ) wr.write_bool( val.to_bool ) end
append_buffer( wr, val )
click to toggle source
# File lib/mingle/bincodec.rb, line 113 def append_buffer( wr, val ) append_type_code( wr, TYPE_CODE_BUFFER ) append_sized_buffer( wr, val.buf ) end
append_enum( wr, val )
click to toggle source
# File lib/mingle/bincodec.rb, line 120 def append_enum( wr, val ) append_type_code( wr, TYPE_CODE_ENUM ) append_type_reference( wr, val.type ) append_identifier( wr, val.value ) end
append_fields( wr, flds )
click to toggle source
# File lib/mingle/bincodec.rb, line 177 def append_fields( wr, flds ) flds.each_pair do |fld, val| unless val.is_a?( MingleNull ) append_type_code( wr, TYPE_CODE_FIELD ) append_identifier( wr, fld ) append_value( wr, val ) end end append_type_code( wr, TYPE_CODE_END ) end
append_float32( wr, val )
click to toggle source
# File lib/mingle/bincodec.rb, line 108 def append_float32( wr, val ) append_num( wr, val, TYPE_CODE_FLOAT32, :write_float32 ) end
append_float64( wr, val )
click to toggle source
# File lib/mingle/bincodec.rb, line 103 def append_float64( wr, val ) append_num( wr, val, TYPE_CODE_FLOAT64, :write_float64 ) end
append_identifier( wr, id )
click to toggle source
# File lib/mingle/bincodec.rb, line 57 def append_identifier( wr, id ) BinWriter.as_bin_writer( wr ).write_identifier( id ) end
append_int32( wr, val )
click to toggle source
# File lib/mingle/bincodec.rb, line 88 def append_int32( wr, val ) append_num( wr, val, TYPE_CODE_INT32, :write_int32 ) end
append_int64( wr, val )
click to toggle source
# File lib/mingle/bincodec.rb, line 83 def append_int64( wr, val ) append_num( wr, val, TYPE_CODE_INT64, :write_int64 ) end
append_list( wr, val )
click to toggle source
# File lib/mingle/bincodec.rb, line 143 def append_list( wr, val ) append_type_code( wr, TYPE_CODE_LIST ) wr.write_int32( -1 ) val.each { |elt| append_value( wr, elt ) } append_type_code( wr, TYPE_CODE_END ) end
append_num( wr, mg_num, type_code, enc_meth )
click to toggle source
# File lib/mingle/bincodec.rb, line 76 def append_num( wr, mg_num, type_code, enc_meth ) append_type_code( wr, type_code ) wr.send( enc_meth, mg_num.num ) end
append_sized_buffer( wr, buf )
click to toggle source
# File lib/mingle/bincodec.rb, line 47 def append_sized_buffer( wr, buf ) wr.write_buffer32( buf ) end
append_string( wr, str )
click to toggle source
# File lib/mingle/bincodec.rb, line 69 def append_string( wr, str ) append_type_code( wr, TYPE_CODE_STRING ) wr.write_utf8( str.to_s ) end
append_struct( wr, ms )
click to toggle source
# File lib/mingle/bincodec.rb, line 192 def append_struct( wr, ms ) append_type_code( wr, TYPE_CODE_STRUCT ) wr.write_int32( -1 ) append_type_reference( wr, ms.type ) append_fields( wr, ms.fields ) end
append_symbol_map( wr, val )
click to toggle source
# File lib/mingle/bincodec.rb, line 136 def append_symbol_map( wr, val ) append_type_code( wr, TYPE_CODE_SYMBOL_MAP ) append_fields( wr, val ) end
append_timestamp( wr, val )
click to toggle source
# File lib/mingle/bincodec.rb, line 128 def append_timestamp( wr, val ) append_type_code( wr, TYPE_CODE_TIMESTAMP ) wr.write_int64( val.time.to_i ) wr.write_int32( val.time.nsec ) end
append_type_code( wr, code )
click to toggle source
# File lib/mingle/bincodec.rb, line 42 def append_type_code( wr, code ) wr.write_int8( code ) end
append_type_reference( wr, typ )
click to toggle source
# File lib/mingle/bincodec.rb, line 52 def append_type_reference( wr, typ ) BinWriter.as_bin_writer( wr ).write_type_reference( typ ) end
append_uint32( wr, val )
click to toggle source
# File lib/mingle/bincodec.rb, line 93 def append_uint32( wr, val ) append_num( wr, val, TYPE_CODE_UINT32, :write_uint32 ) end
append_uint64( wr, val )
click to toggle source
# File lib/mingle/bincodec.rb, line 98 def append_uint64( wr, val ) append_num( wr, val, TYPE_CODE_UINT64, :write_uint64 ) end
append_value( wr, val )
click to toggle source
# File lib/mingle/bincodec.rb, line 152 def append_value( wr, val ) case val when MingleBoolean then append_boolean( wr, val ) when MingleString then append_string( wr, val ) when MingleInt32 then append_int32( wr, val ) when MingleInt64 then append_int64( wr, val ) when MingleUint32 then append_uint32( wr, val ) when MingleUint64 then append_uint64( wr, val ) when MingleFloat32 then append_float32( wr, val ) when MingleFloat64 then append_float64( wr, val ) when MingleBuffer then append_buffer( wr, val ) when MingleEnum then append_enum( wr, val ) when MingleTimestamp then append_timestamp( wr, val ) when MingleStruct then append_struct( wr, val ) when MingleSymbolMap then append_symbol_map( wr, val ) when MingleList then append_list( wr, val ) when MingleNull then append_type_code( wr, TYPE_CODE_NULL ) else raise "Unhandled value type: #{val.class}" end end
cur_pos( scanner )
click to toggle source
# File lib/mingle/bincodec.rb, line 230 def cur_pos( scanner ) scanner.pos end
decode_raise( pos_obj, msg )
click to toggle source
# File lib/mingle/bincodec.rb, line 235 def decode_raise( pos_obj, msg ) off = case pos_obj when Fixnum then pos_obj when Io::BinaryReader then last_pos( pos_obj ) else raise "Unexpected pos_obj of type #{pos_obj.class}" end codec_raise( "[offset #{off}]: #{msg}" ) end
expect_type_code( scanner, code_sym )
click to toggle source
# File lib/mingle/bincodec.rb, line 257 def expect_type_code( scanner, code_sym ) code_val = Mingle::BinCodec.const_get( code_sym ) if ( b = scanner.read_int8 ) == code_val code_val else type_code_expect_raise( code_sym, b, last_pos( scanner ) ) end end
expect_type_code_end( scanner )
click to toggle source
# File lib/mingle/bincodec.rb, line 269 def expect_type_code_end( scanner ) expect_type_code( scanner, :TYPE_CODE_END ) end
last_pos( scanner )
click to toggle source
Useful when reporting errors; returns the index just before pos, which was presumably related to the error
# File lib/mingle/bincodec.rb, line 225 def last_pos( scanner ) scanner.pos - 1 end
raise_unrecognized_value_code( tc, pos )
click to toggle source
# File lib/mingle/bincodec.rb, line 247 def raise_unrecognized_value_code( tc, pos ) decode_raise( pos, sprintf( "Unrecognized value code: 0x%02x", tc ) ) end
read_field( scanner, flds )
click to toggle source
# File lib/mingle/bincodec.rb, line 284 def read_field( scanner, flds ) id = read_identifier( scanner ) fld = read_value( scanner ) flds[ id ] = fld end
read_fields( scanner )
click to toggle source
# File lib/mingle/bincodec.rb, line 293 def read_fields( scanner ) flds = {} while ( tc = scanner.read_int8 ) != TYPE_CODE_END if tc == TYPE_CODE_FIELD read_field( scanner, flds ) else type_code_expect_raise( :TYPE_CODE_FIELD, tc, cur_pos( scanner ) ) end end MingleSymbolMap.create( flds ) end
read_identifier( scanner )
click to toggle source
# File lib/mingle/bincodec.rb, line 279 def read_identifier( scanner ) return BinReader.as_bin_reader( scanner ).read_identifier end
read_mg_boolean( scanner )
click to toggle source
# File lib/mingle/bincodec.rb, line 310 def read_mg_boolean( scanner ) case b = scanner.read_int8 when 0x00 then MingleBoolean::FALSE when 0x01 then MingleBoolean::TRUE else raise "Unexpected bool val: #{to_hex_byte( b )}" end end
read_mg_buffer( scanner )
click to toggle source
# File lib/mingle/bincodec.rb, line 352 def read_mg_buffer( scanner ) MingleBuffer.new( scanner.read_buffer32 ) end
read_mg_enum( scanner )
click to toggle source
# File lib/mingle/bincodec.rb, line 357 def read_mg_enum( scanner ) typ = read_type_reference( scanner ) value = read_identifier( scanner ) MingleEnum.new( :type => typ, :value => value ) end
read_mg_list( scanner )
click to toggle source
# File lib/mingle/bincodec.rb, line 375 def read_mg_list( scanner ) res = [] len = scanner.read_int32 # ignored for now while ( tc = scanner.read_int8 ) != TYPE_CODE_END res << read_value( scanner, tc ) end MingleList.new( res ) end
read_mg_string( scanner )
click to toggle source
# File lib/mingle/bincodec.rb, line 320 def read_mg_string( scanner ) MingleString.new( scanner.read_utf8 ) end
read_mg_struct( scanner )
click to toggle source
# File lib/mingle/bincodec.rb, line 325 def read_mg_struct( scanner ) sz = scanner.read_int32 typ = read_type_reference( scanner ) flds = read_fields( scanner ) MingleStruct.new( :type => typ, :fields => flds ) end
read_mg_timestamp( scanner )
click to toggle source
# File lib/mingle/bincodec.rb, line 366 def read_mg_timestamp( scanner ) secs, nsec = scanner.read_int64, scanner.read_int32 t = Time.at( secs, nsec.to_f / 1000.0 ) MingleTimestamp.new( t, false ) end
read_type_reference( scanner )
click to toggle source
# File lib/mingle/bincodec.rb, line 274 def read_type_reference( scanner ) return BinReader.as_bin_reader( scanner ).read_type_reference end
read_value( scanner, typ = scanner.read_int8 )
click to toggle source
# File lib/mingle/bincodec.rb, line 388 def read_value( scanner, typ = scanner.read_int8 ) case typ when TYPE_CODE_BOOLEAN then read_mg_boolean( scanner ) when TYPE_CODE_INT64 then read_mg_int64( scanner ) when TYPE_CODE_INT32 then read_mg_int32( scanner ) when TYPE_CODE_UINT32 then read_mg_uint32( scanner ) when TYPE_CODE_UINT64 then read_mg_uint64( scanner ) when TYPE_CODE_FLOAT64 then read_mg_float64( scanner ) when TYPE_CODE_FLOAT32 then read_mg_float32( scanner ) when TYPE_CODE_STRING then read_mg_string( scanner ) when TYPE_CODE_BUFFER then read_mg_buffer( scanner ) when TYPE_CODE_ENUM then read_mg_enum( scanner ) when TYPE_CODE_TIMESTAMP then read_mg_timestamp( scanner ) when TYPE_CODE_STRUCT then read_mg_struct( scanner ) when TYPE_CODE_SYMBOL_MAP then read_fields( scanner ) when TYPE_CODE_LIST then read_mg_list( scanner ) when TYPE_CODE_NULL then MingleNull::INSTANCE else raise_unrecognized_value_code( typ, scanner ) end end
to_hex_byte( i )
click to toggle source
# File lib/mingle/bincodec.rb, line 218 def to_hex_byte( i ) sprintf( "0x%02x", i % 256 ) end
type_code_expect_raise( code_sym, code_act, pos )
click to toggle source
# File lib/mingle/bincodec.rb, line 252 def type_code_expect_raise( code_sym, code_act, pos ) raise_unrecognized_value_code( code_act, pos ) end
validate_from_buffer_args( buf )
click to toggle source
# File lib/mingle/bincodec.rb, line 412 def validate_from_buffer_args( buf ) not_nil( buf, :buf ) RubyVersions.when_19x do buf.encoding == Encoding::BINARY or codec_raise( "Buffer encoding is not binary" ) end unless ( tc = @conv.read_int8( buf[ 0, 1 ] ) ) == TYPE_CODE_STRUCT raise_unrecognized_value_code( tc, 0 ) end end