Class: BinaryCodec::Uint

Inherits:
ComparableSerializedType show all
Defined in:
lib/binary-codec/types/uint.rb

Constant Summary collapse

BASE10_UINT64_FIELDS =

UInt64 fields that rippled renders in base 10 rather than as hex. They hold MPToken amounts, where a hex string would be a needless surprise.

%w[
  MaximumAmount
  OutstandingAmount
  MPTAmount
  LockedAmount
].freeze

Instance Attribute Summary

Attributes inherited from SerializedType

#bytes

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from ComparableSerializedType

#eq, #gt, #gte, #lt, #lte

Methods inherited from SerializedType

from_bytes, from_hex, from_json, get_type_by_name, #to_byte_sink, #to_bytes, #to_hex

Constructor Details

#initialize(byte_buf = nil) ⇒ Uint

Returns a new instance of Uint.



21
22
23
# File 'lib/binary-codec/types/uint.rb', line 21

def initialize(byte_buf = nil)
  super(byte_buf || Array.new(self.class.width, 0))
end

Class Method Details

.from(value) ⇒ Uint

Creates a new Uint instance from a value.

Parameters:

  • value (Uint, String, Integer)

    The value to convert.

Returns:

  • (Uint)

    The created instance.

Raises:

  • (StandardError)


28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/binary-codec/types/uint.rb', line 28

def self.from(value)
  return value if value.is_a?(self)

  if value.is_a?(String)
    # Special handling for TransactionType and LedgerEntryType
    if self == Uint16
      transaction_types = Definitions.instance.instance_variable_get(:@transaction_types)
      if transaction_types&.key?(value)
        return new(int_to_bytes(transaction_types[value], width))
      end
      ledger_entry_types = Definitions.instance.instance_variable_get(:@ledger_entry_types)
      if ledger_entry_types&.key?(value)
        return new(int_to_bytes(ledger_entry_types[value], width))
      end
    elsif self == Uint8
      transaction_results = Definitions.instance.instance_variable_get(:@transaction_results)
      if transaction_results&.key?(value)
        return new(int_to_bytes(transaction_results[value], width))
      end
    end

    # Handle hex strings or numeric strings
    if valid_hex?(value) && value.length == self.width * 2
      return new(hex_to_bytes(value))
    end
    return new(int_to_bytes(value.to_i, width))
  end

  if value.is_a?(Integer)
    return new(int_to_bytes(value, width))
  end

  raise StandardError, "Cannot construct #{self} from the value given"
end

.from_parser(parser, _hint = nil) ⇒ Uint

Creates a Uint instance from a parser.

Parameters:

  • parser (BinaryParser)

    The parser to read from.

  • _hint (Integer, nil) (defaults to: nil)

    Unused hint.

Returns:

  • (Uint)

    The created instance.



67
68
69
# File 'lib/binary-codec/types/uint.rb', line 67

def self.from_parser(parser, _hint = nil)
  new(parser.read(width))
end

.widthInteger

Returns the width of the Uint type in bytes.

Returns:

  • (Integer)

    The width.



17
18
19
# File 'lib/binary-codec/types/uint.rb', line 17

def self.width
  @width
end

Instance Method Details

#compare_to(other) ⇒ Integer

Returns Comparison result (-1, 0, or 1).

Parameters:

  • other (Uint)

    The other Uint to compare to.

Returns:

  • (Integer)

    Comparison result (-1, 0, or 1).



122
123
124
# File 'lib/binary-codec/types/uint.rb', line 122

def compare_to(other)
  value_of <=> other.value_of
end

#to_json(_definitions = nil, _field_name = nil) ⇒ Integer, String

Returns the JSON representation of the Uint.

Returns:

  • (Integer, String)

    The value.



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/binary-codec/types/uint.rb', line 79

def to_json(_definitions = nil, _field_name = nil)
  # Special handling for TransactionType, LedgerEntryType, and TransactionResult
  # ONLY when requested via a field name that matches.
  if _field_name == 'TransactionType'
    val = value_of
    transaction_types = Definitions.instance.instance_variable_get(:@transaction_types)
    if transaction_types
      name = transaction_types.key(val)
      return name if name
    end
  elsif _field_name == 'LedgerEntryType'
    val = value_of
    ledger_entry_types = Definitions.instance.instance_variable_get(:@ledger_entry_types)
    if ledger_entry_types
      name = ledger_entry_types.key(val)
      return name if name
    end
  elsif _field_name == 'TransactionResult'
    val = value_of
    transaction_results = Definitions.instance.instance_variable_get(:@transaction_results)
    if transaction_results
      name = transaction_results.key(val)
      return name if name
    end
  end

  # rippled renders the narrow unsigned integers as JSON numbers and UInt64
  # as a 16 digit hex string, because a UInt64 does not survive a round trip
  # through a JSON number. The MPToken amount fields are the exception to
  # that exception: they are UInt64 but carry a base 10 string.
  #
  # Everything wider than 8 bytes (Uint96 and up) is hash-like and stays
  # hex. Do not widen the numeric branch to cover it.
  val = value_of
  return val if self.class.width < 8
  return val.to_s if self.class.width == 8 && BASE10_UINT64_FIELDS.include?(_field_name)

  # Hex is unsigned, so a negative signed value has to wrap first.
  val += (1 << (self.class.width * 8)) if val < 0
  val.to_s(16).upcase.rjust(self.class.width * 2, '0')
end

#value_ofInteger

Returns the numeric value of the Uint.

Returns:

  • (Integer)

    The numeric value.



73
74
75
# File 'lib/binary-codec/types/uint.rb', line 73

def value_of
  @bytes.reduce(0) { |acc, byte| (acc << 8) + byte }
end