Class: Bytepack::Decimal

Inherits:
FixedSize show all
Defined in:
lib/bytepack/basic/fixed_size/decimal.rb

Constant Summary collapse

DIRECTIVE =
'C16'
NULL_INDICATOR =

NULL indicator for object type serializations

-170141183460469231731687303715884105728 # NULL indicator for object type serializations
LENGTH =
16
PRECISION =
38
SCALE =
12

Class Method Summary collapse

Methods inherited from Basic

bytesToInt, intToBytes, preprocess

Methods inherited from Struct

classifyDataType, config, packingDataType, single_type_array?, testpacking

Class Method Details

.deserialize(val, offset = 0) ⇒ Object



37
38
39
40
41
42
43
44
# File 'lib/bytepack/basic/fixed_size/decimal.rb', line 37

def deserialize(val, offset = 0)
  unscaled = bytesToInt(self::LENGTH, val, offset)
  if unscaled != self::NULL_INDICATOR
    unscaled = unscaled.to_s
    scaled = unscaled.insert(unscaled.size - self::SCALE, ".")
    BigDecimal(scaled)
  end
end

.pack(val) ⇒ Object



13
14
15
# File 'lib/bytepack/basic/fixed_size/decimal.rb', line 13

def pack(val)
  (val == self::NULL_INDICATOR || val.nil?) ? intToBytes(self::LENGTH, self::NULL_INDICATOR) : serialize(val)
end

.serialize(val) ⇒ Object

Raises:

  • (::ArgumentError)


21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/bytepack/basic/fixed_size/decimal.rb', line 21

def serialize(val)
  num = case val
  when BigDecimal then val
  else val.to_d
  end
  sign, digits, base, exponent = *num.split
  scale = digits.size - exponent
  precision = digits.size
  raise(::ArgumentError, "Scale of this decimal is #{scale} and the max is #{self::SCALE}") if scale > self::SCALE
  rest = precision - scale
  raise(::ArgumentError, "Precision to the left of the decimal point is #{rest} and the max is #{self::PRECISION-self::SCALE}") if rest > 26
  scale_factor = self::SCALE - scale
  unscaled_int = sign * digits.to_i * base ** scale_factor # Unscaled integer
  intToBytes(self::LENGTH, unscaled_int)
end

.unpack(bytes, offset = 0) ⇒ Object



17
18
19
# File 'lib/bytepack/basic/fixed_size/decimal.rb', line 17

def unpack(bytes, offset = 0)
  [deserialize(bytes, offset), offset + self::LENGTH]
end