class ErlangBitstream

Constants

TYPES

Public Class Methods

new() click to toggle source
# File lib/inspec/utils/erlang_parser.rb, line 81
def initialize
  @data = []     # a stream of 8-bit numbers
  @cur_bits = "" # a string of binary bits 10010010...
end

Public Instance Methods

add(i) click to toggle source
# File lib/inspec/utils/erlang_parser.rb, line 101
def add(i)
  if i[:integer].nil? && i[:string].nil?
    raise "No data provided, internal error for binary-stream processing!"
  end

  s = bit_size(i[:size], i[:type])
  unless i[:string].nil?
    str2int(i[:string].to_s, i[:type]).map { |e| add_bits(int2bits(e, 8)) }
  else
    add_int(i[:integer], s)
  end
rescue RuntimeError => e
  raise "Error processing Erlang bit string "\
        "'#{i[:string] || i[:integer]}:#{i[:size]}/#{i[:type]}'. #{e.message}"
end
add_bits(s) click to toggle source
# File lib/inspec/utils/erlang_parser.rb, line 136
def add_bits(s)
  b = (@cur_bits + s).scan(/.{1,8}/)
  @data += b[0..-2].map { |x| x.to_i(2) }
  @cur_bits = b.last
end
add_int(v, size) click to toggle source
# File lib/inspec/utils/erlang_parser.rb, line 131
def add_int(v, size)
  x = v.to_i & (2**size - 1) # only get the bits specified in size
  add_bits(int2bits(x, size))
end
bit_size(size, type) click to toggle source
# File lib/inspec/utils/erlang_parser.rb, line 94
def bit_size(size, type)
  raise "Cannot specify size and type at the same time." if !type.nil? && !size.nil?
  return (size || 8).to_i if type.nil?

  TYPES[type] || raise("Cannot handle binary-stream type #{type}")
end
int2bits(i, len) click to toggle source
# File lib/inspec/utils/erlang_parser.rb, line 127
def int2bits(i, len)
  format("%0#{len}b", i)
end
str2int(s, type) click to toggle source
# File lib/inspec/utils/erlang_parser.rb, line 117
def str2int(s, type)
  case type
  when "utf8" then s.encode("utf-8").unpack("C*")
  when "utf16" then s.encode("utf-16").unpack("C*").drop(2)
  when "utf32" then s.encode("utf-32").unpack("C*").drop(4)
  when "integer", "float" then raise "Cannot handle bit string as type #{type}"
  else s.split("").map { |x| x.ord & 0xff }
  end
end
value(encoding = "utf-8") click to toggle source
# File lib/inspec/utils/erlang_parser.rb, line 142
def value(encoding = "utf-8")
  # fill in the rest
  rest = "0" * (8 - @cur_bits.length) + @cur_bits
  arr = @data + [rest.to_i(2)]
  s = arr.pack("C*")
  s.force_encoding(encoding) unless encoding.nil?
  s
end