For a Ruby program I’m writing, I’m receiving binary data over a

network. For most of the data I need to read, String#unpack works like

a charm. However, some of the data I receive is 64 bit 2s complement

integers, and since String#unpack does not have a mode for 64 bit

numbers I’m having trouble figuring out how to get a Bignum from the

binary data.

As I’ve mentioned, the data is in 2s complement representation[1] such

that 1 is encoded as “\001\000\000\000\000\000\000\000” and -1 is

encoded as “\377\377\377\377\377\377\377\377” (those are both little

endian, by the way).

My question is, what’s the best way to make a Ruby integer out of this

binary string? I’ve already tried constructing a hexadecimal

representation of the bytes and passing that to the Kernel::Integer

method before realizing that that method is doing direct conversion

rather than presuming 2s complement representation. I also tried

massaging the result of this process by doing a bit-wise complement and

adding one (trying to perform the 2s complement myself), but that

doesn’t work either.

Any ideas? Please note that I need a solution that works for big endian

and little endian, since the data can arrive in either order.

Thanks,

Jason Voegele

[1] The data is encoded like this:

lsb = __cdr_lsb(val) # least significant 4 bytes

msb = __cdr_msb(val) # most significant 4 bytes

lval = Kernel::big_endian? ? [msb, lsb] : [lsb, msb]

lval.pack(‘ll’)

I’ve added the big_endian? method to Kernel to determine whether the

underlying platform is big endian or not.