user1056142
user1056142

Reputation: 11

Packing a long binary integer in Ruby

I'm trying to send a very long binary integer over UDP (on the order of 200 bits). When I try to use Array's pack method, it complains the string I'm trying to convert is too large.

Am I going about this the wrong way?

ruby-1.8.7-p352 :003 > [0b1101001010101101111010100101010011010101010110010101010101010010010101001010101010101011101010101010101111010101010101010101].pack('i')
RangeError: bignum too big to convert into `unsigned long'
from (irb):3:in `pack'
from (irb):3

This number is supposed to represent a DNS query packet (this is for a homework assignment; we're not allowed to use any DNS libraries).

Upvotes: 1

Views: 2309

Answers (2)

sarnold
sarnold

Reputation: 104050

You need to break apart your number into smaller pieces. Probably best is to encode 32 bits at a time:

> num = 0b1101001010101101111010100101010011010101010110010101010101010010010101001010101010101011101010101010101111010101010101010101
=> 17502556204775004286774747314501014869
> low_1 = num & 0xFFFFFFFF
=> 2864534869
> low_2 = (num >> 32) & 0xFFFFFFFF
=> 625650362
> low_3 = (num >> 64) & 0xFFFFFFFF
=> 1297454421
> low_4 = (num >> 96) & 0xFFFFFFFF
=> 220913317
> (low_4 << 96) + (low_3 << 64) + (low_2 << 32) + low_1
=> 17502556204775004286774747314501014869
> msg = [low_4, low_3, low_2, low_1].pack("NNNN")
=> "\r*\336\245MU\225U%J\252\272\252\275UU"
> msg.unpack("NNNN").inject {|sum, elem| (sum << 32) + elem}
=> 17502556204775004286774747314501014869

I prefer 32 bits here because you pack these in Network Byte Order, which makes interopation with other platforms much easier. The pack() method doesn't provide a network byte order 64-bit integer. (Which isn't too surprising, since POSIX doesn't provide a 64-bit routine.)

Upvotes: 4

Igor Kapkov
Igor Kapkov

Reputation: 3899

Ruby 1.9.3 works normally.

irb(main):001:0> [0b1101001010101101111010100101010011010101010110010101010101010010010101001010101010101011101010101010101111010101010101010101].pack('i')
=> "UU\xBD\xAA"

Upvotes: -1

Related Questions