Class: Eth::Abi::Type
- Inherits:
-
Object
- Object
- Eth::Abi::Type
- Defined in:
- lib/eth/abi/type.rb
Overview
Provides a class to handle and parse common ABI types.
Defined Under Namespace
Classes: ParseError
Instance Attribute Summary collapse
-
#base_type ⇒ Object
readonly
The base attribute, e.g.,
string
orbytes
. -
#components ⇒ Object
readonly
The components of a tuple type.
-
#dimensions ⇒ Object
readonly
The dimension attribute, e.g.,
[10]
for an array of size 10. -
#name ⇒ Object
readonly
The name of tuple component.
-
#sub_type ⇒ Object
readonly
The sub-type attribute, e.g.,
256
as size of an uint256.
Class Method Summary collapse
-
.size_type ⇒ Eth::Abi::Type
Creates a new uint256 type used for size.
Instance Method Summary collapse
-
#==(another_type) ⇒ Boolean
Compares two types for their attributes.
-
#dynamic? ⇒ Boolean
Helpes to determine whether array is of dynamic size.
-
#initialize(base_type, sub_type, dimensions, components = nil, component_name = nil) ⇒ Eth::Abi::Type
constructor
Create a new Type object for base types, sub types, and dimensions.
-
#nested_sub ⇒ Eth::Abi::Type
Types can have nested sub-types in arrays.
-
#parse(type, components = nil, component_name = nil) ⇒ Eth::Abi::Type
Attempts to parse a string containing a common Solidity type.
-
#size ⇒ Integer
Computes the size of a type if possible.
-
#to_s ⇒ String
Allows exporting the type as string.
Constructor Details
#initialize(base_type, sub_type, dimensions, components = nil, component_name = nil) ⇒ Eth::Abi::Type
Create a new Type object for base types, sub types, and dimensions. Should not be used; use #parse instead.
53 54 55 56 57 58 59 60 |
# File 'lib/eth/abi/type.rb', line 53 def initialize(base_type, sub_type, dimensions, components = nil, component_name = nil) sub_type = sub_type.to_s @base_type = base_type @sub_type = sub_type @dimensions = dimensions @components = components @name = component_name end |
Instance Attribute Details
#base_type ⇒ Object (readonly)
The base attribute, e.g., string
or bytes
.
30 31 32 |
# File 'lib/eth/abi/type.rb', line 30 def base_type @base_type end |
#components ⇒ Object (readonly)
The components of a tuple type.
39 40 41 |
# File 'lib/eth/abi/type.rb', line 39 def components @components end |
#dimensions ⇒ Object (readonly)
The dimension attribute, e.g., [10]
for an array of size 10.
36 37 38 |
# File 'lib/eth/abi/type.rb', line 36 def dimensions @dimensions end |
#name ⇒ Object (readonly)
The name of tuple component.
42 43 44 |
# File 'lib/eth/abi/type.rb', line 42 def name @name end |
#sub_type ⇒ Object (readonly)
The sub-type attribute, e.g., 256
as size of an uint256.
33 34 35 |
# File 'lib/eth/abi/type.rb', line 33 def sub_type @sub_type end |
Class Method Details
.size_type ⇒ Eth::Abi::Type
Creates a new uint256 type used for size.
118 119 120 |
# File 'lib/eth/abi/type.rb', line 118 def self.size_type @size_type ||= new("uint", 256, []) end |
Instance Method Details
#==(another_type) ⇒ Boolean
Compares two types for their attributes.
126 127 128 129 130 |
# File 'lib/eth/abi/type.rb', line 126 def ==(another_type) base_type == another_type.base_type and sub_type == another_type.sub_type and dimensions == another_type.dimensions end |
#dynamic? ⇒ Boolean
Helpes to determine whether array is of dynamic size.
152 153 154 |
# File 'lib/eth/abi/type.rb', line 152 def dynamic? size.nil? end |
#nested_sub ⇒ Eth::Abi::Type
Types can have nested sub-types in arrays.
159 160 161 |
# File 'lib/eth/abi/type.rb', line 159 def nested_sub @nested_sub ||= self.class.new(base_type, sub_type, dimensions[0...-1], components, name) end |
#parse(type, components = nil, component_name = nil) ⇒ Eth::Abi::Type
Attempts to parse a string containing a common Solidity type. Creates a new Type upon success (using konstructor).
73 74 75 76 77 78 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 |
# File 'lib/eth/abi/type.rb', line 73 def parse(type, components = nil, component_name = nil) if type.is_a?(Type) @base_type = type.base_type @sub_type = type.sub_type @dimensions = type.dimensions @components = type.components @name = type.name return end # ensure the type string is reasonable before attempting to parse raise ParseError, "Invalid type format" unless type.is_a?(String) && type.bytesize <= 256 if type.start_with?("tuple(") inner, rest = extract_tuple(type) inner_types = split_tuple_types(inner) inner_types.each { |t| Type.parse(t) } base_type = "tuple" sub_type = "" dimension = rest else match = /\A([a-z]+)([0-9]*x?[0-9]*)((?:\[\d+\]|\[\])*)\z/.match(type) raise ParseError, "Invalid type format" unless match _, base_type, sub_type, dimension = match.to_a end # type dimension can only be numeric or empty for dynamic arrays dims = dimension.scan(/\[\d+\]|\[\]/) raise ParseError, "Unknown characters found in array declaration" if dims.join != dimension # enforce base types validate_base_type base_type, sub_type # return a new Type (using konstructor) sub_type = sub_type.to_s @base_type = base_type @sub_type = sub_type @dimensions = dims.map { |x| x == "[]" ? 0 : x[1...-1].to_i } @components = components.map { |component| Abi::Type.parse(component["type"], component.dig("components"), component.dig("name")) } if components&.any? @name = component_name end |
#size ⇒ Integer
Computes the size of a type if possible.
135 136 137 138 139 140 141 142 143 144 145 146 147 |
# File 'lib/eth/abi/type.rb', line 135 def size s = nil if dimensions.empty? if !(["string", "bytes", "tuple"].include?(base_type) and sub_type.empty?) s = 32 elsif base_type == "tuple" and components&.none?(&:dynamic?) s = components.sum(&:size) end elsif dimensions.last != 0 and !nested_sub.dynamic? s = dimensions.last * nested_sub.size end @size ||= s end |
#to_s ⇒ String
Allows exporting the type as string.
166 167 168 169 170 171 172 173 174 175 176 177 178 |
# File 'lib/eth/abi/type.rb', line 166 def to_s if base_type == "tuple" "(" + components.map(&:to_s).join(",") + ")" + (dimensions.size > 0 ? dimensions.map { |x| "[#{x == 0 ? "" : x}]" }.join : "") elsif dimensions.empty? if %w[string bytes].include?(base_type) and sub_type.empty? base_type else "#{base_type}#{sub_type}" end else "#{base_type}#{sub_type}#{dimensions.map { |x| "[#{x == 0 ? "" : x}]" }.join}" end end |