Class: HrrRbSsh::DataType::Mpint

Inherits:
HrrRbSsh::DataType show all
Defined in:
lib/hrr_rb_ssh/data_type/mpint.rb

Overview

Mpint provides methods to convert integer value and multiple precision integer in two’s complement as binary string each other.

Class Method Summary collapse

Class Method Details

.decode(io) ⇒ ::Integer

Convert multiple precision integer in two’s complement as binary string into integer value.

Parameters:

  • io (::IO)

    IO instance that has buffer to be read

Returns:

  • (::Integer)

    converted integer value



40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/hrr_rb_ssh/data_type/mpint.rb', line 40

def self.decode io
  length = io.read(4).unpack("N")[0]
  hex_str = io.read(length).unpack("H*")[0]
  # get temporal integer value
  value = hex_str.hex
  if length == 0
    0
  elsif value[(length * 8) - 1] == 0
    value
  else
    num_bytes = if hex_str.start_with?("ff") then length - 1 else length end
    - (((~ value) & ((1 << (num_bytes * 8)) - 1)) + 1)
  end
end

.encode(arg) ⇒ ::String

Convert integer value into multiple precision integer in two’s complement as binary string.

Parameters:

  • arg (::Integer)

    integer value to be converted

Returns:

  • (::String)

    converted multiple precision integer in two’s complement as binary string

Raises:

  • (::ArgumentError)

    when arg is not an integer value



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/hrr_rb_ssh/data_type/mpint.rb', line 15

def self.encode arg
  unless arg.kind_of? ::Integer
    raise ArgumentError, "must be a kind of Integer, but got #{arg.inspect}"
  end
  bn = ::OpenSSL::BN.new(arg)
  if bn < 0
    # get 2's complement
    tc = bn.to_i & ((1 << (bn.num_bytes * 8)) - 1)
    # get hex representation
    hex_str = "%x" % tc

    if tc[(bn.num_bytes * 8) - 1] == 1
      [bn.num_bytes, hex_str].pack("NH*")
    else
      [bn.num_bytes + 1, "ff" + hex_str].pack("NH*")
    end
  else
    bn.to_s(0)
  end
end