Module: MessagePack::Bigint

Defined in:
lib/msgpack/bigint.rb

Constant Summary collapse

CHUNK_BITLENGTH =

We split the bigint in 32bits chunks so that individual part fits into a MRI immediate Integer.

32
FORMAT =
'CL>*'
BASE =

On 2.6 and older since we can’t address arbitrary bitranges, so we fallback to shifting the bigint. This means that after each shift, we may allocate another Integer instance.

(2**CHUNK_BITLENGTH) - 1

Class Method Summary collapse

Class Method Details

.from_msgpack_ext(data) ⇒ Object



55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/msgpack/bigint.rb', line 55

def self.from_msgpack_ext(data)
  parts = data.unpack(FORMAT)

  sign = parts.shift
  sum = parts.pop.to_i

  parts.reverse_each do |part|
    sum = sum << CHUNK_BITLENGTH
    sum += part
  end

  sign == 0 ? sum : -sum
end

.to_msgpack_ext(bigint) ⇒ Object

Starting from Ruby 2.7 we can address arbitrary bitranges inside an Integer with Integer#[] This allows to not allocate any Integer.



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/msgpack/bigint.rb', line 13

def self.to_msgpack_ext(bigint)
  members = []

  if bigint < 0
    bigint = -bigint
    members << 1
  else
    members << 0
  end

  offset = 0
  length = bigint.bit_length
  while offset < length
    members << bigint[offset, CHUNK_BITLENGTH]
    offset += CHUNK_BITLENGTH
  end

  members.pack(FORMAT)
end