module Erlang
Erlang
term classes listed alphabetically
Constants
- TAG_ATOM_CACHE_REF
- TAG_ATOM_EXT
- TAG_ATOM_UTF8_EXT
- TAG_BINARY_EXT
- TAG_BIT_BINARY_EXT
- TAG_COMPRESSED_ZLIB
- TAG_EXPORT_EXT
- TAG_FLOAT_EXT
- TAG_FUN_EXT
- TAG_INTEGER_EXT
- TAG_LARGE_BIG_EXT
- TAG_LARGE_TUPLE_EXT
- TAG_LIST_EXT
- TAG_LOCAL_EXT
- TAG_MAP_EXT
- TAG_NEWER_REFERENCE_EXT
- TAG_NEW_FLOAT_EXT
- TAG_NEW_FUN_EXT
- TAG_NEW_PID_EXT
- TAG_NEW_PORT_EXT
- TAG_NEW_REFERENCE_EXT
- TAG_NIL_EXT
- TAG_PID_EXT
- TAG_PORT_EXT
- TAG_REFERENCE_EXT
- TAG_SMALL_ATOM_EXT
- TAG_SMALL_ATOM_UTF8_EXT
- TAG_SMALL_BIG_EXT
- TAG_SMALL_INTEGER_EXT
- TAG_SMALL_TUPLE_EXT
- TAG_STRING_EXT
- TAG_V4_PORT_EXT
- TAG_VERSION
tag values here www.erlang.org/doc/apps/erts/erl_ext_dist.html
Public Class Methods
binary_to_term(data)
click to toggle source
core functionality
# File lib/erlang.rb, line 308 def self.binary_to_term(data) size = data.bytesize if size <= 1 raise ParseException, 'null input', caller end if data[0].ord != TAG_VERSION raise ParseException, 'invalid version', caller end begin result = binary_to_term_(1, data) if result[0] != size raise ParseException, 'unparsed data', caller end return result[1] rescue NoMethodError => e raise ParseException, 'missing data', e.backtrace rescue TypeError => e raise ParseException, 'missing data', e.backtrace rescue ArgumentError => e raise ParseException, 'missing data', e.backtrace end end
set_undefined(value)
click to toggle source
Elixir use can set to ‘nil’
# File lib/erlang.rb, line 355 def self.set_undefined(value) @@UNDEFINED = value end
term_to_binary(term, compressed = false)
click to toggle source
# File lib/erlang.rb, line 331 def self.term_to_binary(term, compressed = false) data_uncompressed = term_to_binary_(term) if compressed == false return "#{TAG_VERSION.chr}#{data_uncompressed}" else if compressed == true compressed = 6 end if compressed < 0 or compressed > 9 raise InputException, 'compressed in [0..9]', caller end data_compressed = Zlib::Deflate.deflate(data_uncompressed, compressed) size_uncompressed = data_uncompressed.bytesize if size_uncompressed > 4294967295 raise OutputException, 'uint32 overflow', caller end size_uncompressed_packed = [size_uncompressed].pack('N') return "#{TAG_VERSION.chr}#{TAG_COMPRESSED_ZLIB.chr}" \ "#{size_uncompressed_packed}#{data_compressed}" end end
Private Class Methods
bignum_to_binary(term)
click to toggle source
# File lib/erlang.rb, line 820 def self.bignum_to_binary(term) bignum = term.abs if term < 0 sign = 1.chr else sign = 0.chr end l = [] while bignum > 0 do l.push((bignum & 255).chr) bignum >>= 8 end length = l.length if length <= 255 return "#{TAG_SMALL_BIG_EXT.chr}#{length.chr}#{sign}#{l.join}" elsif length <= 4294967295 length_packed = [length].pack('N') return "#{TAG_LARGE_BIG_EXT.chr}#{length_packed}#{sign}#{l.join}" else raise OutputException, 'uint32 overflow', caller end end
binary_to_atom(i, data)
click to toggle source
# File lib/erlang.rb, line 674 def self.binary_to_atom(i, data) tag = data[i].ord i += 1 if tag == TAG_ATOM_EXT j = data[i,2].unpack('n')[0] i += 2 return [i + j, OtpErlangAtom.new(data[i,j])] elsif tag == TAG_ATOM_CACHE_REF return [i + 1, OtpErlangAtom.new(data[i,1].ord)] elsif tag == TAG_SMALL_ATOM_EXT j = data[i,1].ord i += 1 return [i + j, OtpErlangAtom.new(data[i,j])] elsif tag == TAG_ATOM_UTF8_EXT j = data[i,2].unpack('n')[0] i += 2 atom_name = data[i,j].force_encoding('UTF-8') if atom_name.valid_encoding? return [i + j, OtpErlangAtom.new(atom_name)] else raise ParseException, 'invalid atom_name unicode', caller end elsif tag == TAG_SMALL_ATOM_UTF8_EXT j = data[i,1].ord i += 1 atom_name = data[i,j].force_encoding('UTF-8') if atom_name.valid_encoding? return [i + j, OtpErlangAtom.new(atom_name)] else raise ParseException, 'invalid atom_name unicode', caller end else raise ParseException, 'invalid atom tag', caller end end
binary_to_integer(i, data)
click to toggle source
(binary_to_term
Erlang
term primitive type functions)
# File lib/erlang.rb, line 630 def self.binary_to_integer(i, data) tag = data[i].ord i += 1 if tag == TAG_SMALL_INTEGER_EXT return [i + 1, data[i].ord] elsif tag == TAG_INTEGER_EXT value = data[i,4].unpack('N')[0] if 0 != (value & 0x80000000) value = -2147483648 + (value & 0x7fffffff) end return [i + 4, Fixnum.induced_from(value)] else raise ParseException, 'invalid integer tag', caller end end
binary_to_pid(i, data)
click to toggle source
# File lib/erlang.rb, line 646 def self.binary_to_pid(i, data) tag = data[i].ord i += 1 if tag == TAG_NEW_PID_EXT result = binary_to_atom(i, data) i = result[0]; node = result[1] id = data[i,4] i += 4 serial = data[i,4] i += 4 creation = data[i,4] i += 4 return [i, OtpErlangPid.new(node, id, serial, creation)] elsif tag == TAG_PID_EXT result = binary_to_atom(i, data) i = result[0]; node = result[1] id = data[i,4] i += 4 serial = data[i,4] i += 4 creation = data[i] i += 1 return [i, OtpErlangPid.new(node, id, serial, creation)] else raise ParseException, 'invalid pid tag', caller end end
binary_to_term_(i, data)
click to toggle source
binary_to_term
implementation functions
# File lib/erlang.rb, line 363 def self.binary_to_term_(i, data) tag = data[i].ord i += 1 if tag == TAG_NEW_FLOAT_EXT return [i + 8, data[i,8].unpack('G')[0]] elsif tag == TAG_BIT_BINARY_EXT j = data[i,4].unpack('N')[0] i += 4 bits = data[i].ord i += 1 return [i + j, OtpErlangBinary.new(data[i,j], bits)] elsif tag == TAG_ATOM_CACHE_REF return [i + 1, OtpErlangAtom.new(ord(data[i,1]))] elsif tag == TAG_SMALL_INTEGER_EXT return [i + 1, data[i].ord] elsif tag == TAG_INTEGER_EXT value = data[i,4].unpack('N')[0] if 0 != (value & 0x80000000) value = -2147483648 + (value & 0x7fffffff) end return [i + 4, value] elsif tag == TAG_FLOAT_EXT value = data[i,31].partition(0.chr)[0].to_f return [i + 31, value] elsif Set[TAG_V4_PORT_EXT,TAG_NEW_PORT_EXT, TAG_REFERENCE_EXT,TAG_PORT_EXT].include?(tag) result = binary_to_atom(i, data) i = result[0]; node = result[1] if tag == TAG_V4_PORT_EXT id = data[i,8] i += 8 else id = data[i,4] i += 4 end if Set[TAG_V4_PORT_EXT,TAG_NEW_PORT_EXT].include?(tag) creation = data[i,4] i += 4 else creation = data[i] i += 1 if tag == TAG_REFERENCE_EXT return [i, OtpErlangReference.new(node, id, creation)] end end # tag == TAG_V4_PORT_EXT or tag == TAG_NEW_PORT_EXT or # tag == TAG_PORT_EXT return [i, OtpErlangPort.new(node, id, creation)] elsif Set[TAG_NEW_PID_EXT, TAG_PID_EXT].include?(tag) result = binary_to_atom(i, data) i = result[0]; node = result[1] id = data[i,4] i += 4 serial = data[i,4] i += 4 if tag == TAG_NEW_PID_EXT creation = data[i,4] i += 4 elsif tag == TAG_PID_EXT creation = data[i] i += 1 end return [i, OtpErlangPid.new(node, id, serial, creation)] elsif Set[TAG_SMALL_TUPLE_EXT, TAG_LARGE_TUPLE_EXT].include?(tag) if tag == TAG_SMALL_TUPLE_EXT length = data[i].ord i += 1 elsif tag == TAG_LARGE_TUPLE_EXT length = data[i,4].unpack('N')[0] i += 4 end result = binary_to_term_sequence(i, length, data) i = result[0]; tmp = result[1] return [i, tmp] elsif tag == TAG_NIL_EXT return [i, OtpErlangList.new([])] elsif tag == TAG_STRING_EXT j = data[i,2].unpack('n')[0] i += 2 return [i + j, data[i,j]] elsif tag == TAG_LIST_EXT length = data[i,4].unpack('N')[0] i += 4 result = binary_to_term_sequence(i, length, data) i = result[0]; tmp = result[1] result = binary_to_term_(i, data) i = result[0]; tail = result[1] if tail.kind_of?(OtpErlangList) == false or tail.value != [] tmp.push(tail) tmp = OtpErlangList.new(tmp, true) else tmp = OtpErlangList.new(tmp) end return [i, tmp] elsif tag == TAG_BINARY_EXT j = data[i,4].unpack('N')[0] i += 4 return [i + j, OtpErlangBinary.new(data[i,j], 8)] elsif Set[TAG_SMALL_BIG_EXT, TAG_LARGE_BIG_EXT].include?(tag) if tag == TAG_SMALL_BIG_EXT j = data[i].ord i += 1 elsif tag == TAG_LARGE_BIG_EXT j = data[i,4].unpack('N')[0] i += 4 end sign = data[i].ord bignum = 0 (0...j).each do |bignum_index| digit = data[i + j - bignum_index].ord bignum = bignum * 256 + digit end if sign == 1 bignum *= -1 end i += 1 return [i + j, bignum] elsif tag == TAG_NEW_FUN_EXT length = data[i,4].unpack('N')[0] return [i + length, OtpErlangFunction.new(tag, data[i,length])] elsif tag == TAG_EXPORT_EXT old_i = i result = binary_to_atom(i, data) i = result[0]#; name_module = result[1] result = binary_to_atom(i, data) i = result[0]#; function = result[1] if data[i].ord != TAG_SMALL_INTEGER_EXT raise ParseException, 'invalid small integer tag', caller end i += 1 #arity = data[i].ord i += 1 return [i, OtpErlangFunction.new(tag, data[old_i,i - old_i])] elsif Set[TAG_NEWER_REFERENCE_EXT, TAG_NEW_REFERENCE_EXT].include?(tag) j = data[i,2].unpack('n')[0] * 4 i += 2 result = binary_to_atom(i, data) i = result[0]; node = result[1] if tag == TAG_NEWER_REFERENCE_EXT creation = data[i,4] i += 4 elsif tag == TAG_NEW_REFERENCE_EXT creation = data[i] i += 1 end id = data[i,j] return [i + j, OtpErlangReference.new(node, id, creation)] elsif tag == TAG_MAP_EXT length = data[i,4].unpack('N')[0] i += 4 pairs = Hash.new (0...length).each do |length_index| result = binary_to_term_(i, data) i = result[0]; key = result[1] result = binary_to_term_(i, data) i = result[0]; value = result[1] pairs[key] = value end return [i, pairs] elsif tag == TAG_FUN_EXT old_i = i #numfree = data[i,4].unpack('N')[0] i += 4 result = binary_to_pid(i, data) i = result[0]#; pid = result[1] result = binary_to_atom(i, data) i = result[0]#; name_module = result[1] result = binary_to_integer(i, data) i = result[0]#; index = result[1] result = binary_to_integer(i, data) i = result[0]#; uniq = result[1] result = binary_to_term_sequence(i, numfree, data) i = result[0]#; free = result[1] return [i, OtpErlangFunction.new(tag, data[old_i,i - old_i])] elsif Set[TAG_ATOM_UTF8_EXT, TAG_ATOM_EXT].include?(tag) j = data[i,2].unpack('n')[0] i += 2 atom_name = data[i,j] i = i + j if atom_name == 'true' return [i, true] elsif atom_name == 'false' return [i, false] elsif atom_name == @@UNDEFINED return [i, nil] else if tag == TAG_ATOM_UTF8_EXT atom_name = atom_name.force_encoding('UTF-8') if atom_name.valid_encoding? return [i, atom_name.to_sym] else raise ParseException, 'invalid atom_name unicode', caller end else atom_name = atom_name.force_encoding('ISO-8859-1') if atom_name.valid_encoding? return [i, OtpErlangAtom.new(atom_name)] else raise ParseException, 'invalid atom_name latin1', caller end end end elsif Set[TAG_SMALL_ATOM_UTF8_EXT, TAG_SMALL_ATOM_EXT].include?(tag) j = data[i,1].ord i += 1 atom_name = data[i,j] i = i + j if atom_name == 'true' return [i, true] elsif atom_name == 'false' return [i, false] elsif atom_name == @@UNDEFINED return [i, nil] else if tag == TAG_SMALL_ATOM_UTF8_EXT atom_name = atom_name.force_encoding('UTF-8') if atom_name.valid_encoding? return [i, atom_name.to_sym] else raise ParseException, 'invalid atom_name unicode', caller end else atom_name = atom_name.force_encoding('ISO-8859-1') if atom_name.valid_encoding? return [i, OtpErlangAtom.new(atom_name)] else raise ParseException, 'invalid atom_name latin1', caller end end end elsif tag == TAG_COMPRESSED_ZLIB size_uncompressed = data[i,4].unpack('N')[0] if size_uncompressed == 0 raise ParseException, 'compressed data null', caller end i += 4 data_compressed = data[i..-1] j = data_compressed.bytesize data_uncompressed = Zlib::Inflate.inflate(data_compressed) if size_uncompressed != data_uncompressed.bytesize raise ParseException, 'compression corrupt', caller end result = binary_to_term_(0, data_uncompressed) i_new = result[0]; term = result[1] if i_new != size_uncompressed raise ParseException, 'unparsed data', caller end return [i + j, term] elsif tag == TAG_LOCAL_EXT raise ParseException, 'LOCAL_EXT is opaque', caller else raise ParseException, 'invalid tag', caller end end
binary_to_term_sequence(i, length, data)
click to toggle source
# File lib/erlang.rb, line 618 def self.binary_to_term_sequence(i, length, data) sequence = [] (0...length).each do |length_index| result = binary_to_term_(i, data) i = result[0]; element = result[1] sequence.push(element) end return [i, sequence] end
float_to_binary(term)
click to toggle source
# File lib/erlang.rb, line 843 def self.float_to_binary(term) term_packed = [term].pack('G') return "#{TAG_NEW_FLOAT_EXT.chr}#{term_packed}" end
hash_to_binary(term)
click to toggle source
# File lib/erlang.rb, line 792 def self.hash_to_binary(term) length = term.length if length <= 4294967295 term_packed = term.to_a.map{ |element| key_packed = term_to_binary_(element[0]) value_packed = term_to_binary_(element[1]) "#{key_packed}#{value_packed}" }.join length_packed = [length].pack('N') return "#{TAG_MAP_EXT.chr}#{length_packed}#{term_packed}" else raise OutputException, 'uint32 overflow', caller end end
integer_to_binary(term)
click to toggle source
(term_to_binary
Erlang
term primitive type functions)
# File lib/erlang.rb, line 809 def self.integer_to_binary(term) if 0 <= term and term <= 255 return "#{TAG_SMALL_INTEGER_EXT.chr}#{term.chr}" elsif -2147483648 <= term and term <= 2147483647 term_packed = [term].pack('N') return "#{TAG_INTEGER_EXT.chr}#{term_packed}" else return bignum_to_binary(term) end end
string_to_binary(term)
click to toggle source
(term_to_binary
Erlang
term composite type functions)
# File lib/erlang.rb, line 758 def self.string_to_binary(term) length = term.bytesize if length == 0 return TAG_NIL_EXT.chr elsif length <= 65535 length_packed = [length].pack('n') return "#{TAG_STRING_EXT.chr}#{length_packed}#{term}" elsif length <= 4294967295 length_packed = [length].pack('N') term_packed = term.unpack("C#{length}").map{ |c| "#{TAG_SMALL_INTEGER_EXT.chr}#{c}" }.join return "#{TAG_LIST_EXT.chr}#{length_packed}#{term_packed}" \ "#{TAG_NIL_EXT.chr}" else raise OutputException, 'uint32 overflow', caller end end
term_to_binary_(term)
click to toggle source
term_to_binary
implementation functions
# File lib/erlang.rb, line 712 def self.term_to_binary_(term) if term.kind_of?(String) return string_to_binary(term) elsif term.kind_of?(Array) return tuple_to_binary(term) elsif term.kind_of?(Float) return float_to_binary(term) elsif term.kind_of?(Integer) return integer_to_binary(term) elsif term.kind_of?(Hash) return hash_to_binary(term) elsif term.kind_of?(Symbol) return OtpErlangAtom.new(term.to_s).binary elsif term.kind_of?(TrueClass) return OtpErlangAtom.new( 'true'.force_encoding('UTF-8') ).binary elsif term.kind_of?(FalseClass) return OtpErlangAtom.new( 'false'.force_encoding('UTF-8') ).binary elsif term.nil? return OtpErlangAtom.new( @@UNDEFINED.force_encoding('UTF-8') ).binary elsif term.kind_of?(OtpErlangAtom) return term.binary elsif term.kind_of?(OtpErlangList) return term.binary elsif term.kind_of?(OtpErlangBinary) return term.binary elsif term.kind_of?(OtpErlangFunction) return term.binary elsif term.kind_of?(OtpErlangReference) return term.binary elsif term.kind_of?(OtpErlangPort) return term.binary elsif term.kind_of?(OtpErlangPid) return term.binary else raise OutputException, 'unknown ruby type', caller end end
tuple_to_binary(term)
click to toggle source
# File lib/erlang.rb, line 777 def self.tuple_to_binary(term) length = term.length term_packed = term.map{ |element| term_to_binary_(element) }.join if length <= 255 return "#{TAG_SMALL_TUPLE_EXT.chr}#{length.chr}#{term_packed}" elsif length <= 4294967295 length_packed = [length].pack('N') return "#{TAG_LARGE_TUPLE_EXT.chr}#{length_packed}#{term_packed}" else raise OutputException, 'uint32 overflow', caller end end