So I'm working on some MongoDB protocol stuff. All integers are signed little-endian. Using Ruby's standard Array#pack
method, I can convert from an integer to the binary string I want just fine:
positive_one = Array(1).pack('V') #=> '\x01\x00\x00\x00'
negative_one = Array(-1).pack('V') #=> '\xFF\xFF\xFF\xFF'
However, going the other way, the String#unpack
method has the 'V' format documented as specifically returning unsigned integers:
positive_one.unpack('V').first #=> 1
negative_one.unpack('V').first #=> 4294967295
There's no formatter for signed little-endian byte order. I'm sure I could play games with bit-shifting, or write my own byte-mangling method that doesn't use array packing, but I'm wondering if anyone else has run into this and found a simple solution. Thanks very much.
After unpacking with "V"
, you can apply the following conversion
class Integer
def to_signed_32bit
if self & 0x8000_0000 == 0x8000_0000
self - 0x1_0000_0000
else
self
end
end
end
You'll need to change the magic constants 0x1_0000_0000
(which is 2**32
) and 0x8000_0000
(2**31
) if you're dealing with other sizes of integers.