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.
121 122 123 |
# File 'lib/eth/abi/type.rb', line 121 def self.size_type @size_type ||= new("uint", 256, []) end |
Instance Method Details
#==(another_type) ⇒ Boolean
Compares two types for their attributes.
129 130 131 132 133 |
# File 'lib/eth/abi/type.rb', line 129 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.
155 156 157 |
# File 'lib/eth/abi/type.rb', line 155 def dynamic? size.nil? end |
#nested_sub ⇒ Eth::Abi::Type
Types can have nested sub-types in arrays.
162 163 164 |
# File 'lib/eth/abi/type.rb', line 162 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 114 115 116 |
# 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 if type.start_with?("tuple(") || type.start_with?("(") tuple_str = type.start_with?("tuple(") ? type : "tuple#{type}" inner, rest = extract_tuple(tuple_str) inner_types = split_tuple_types(inner) inner_types.each { |t| Type.parse(t) } base_type = "tuple" sub_type = "" dimension = rest components ||= inner_types.map { |t| { "type" => t } } 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 sub_type = "256" if %w[uint int].include?(base_type) && sub_type.empty? 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.
138 139 140 141 142 143 144 145 146 147 148 149 150 |
# File 'lib/eth/abi/type.rb', line 138 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.
169 170 171 172 173 174 175 176 177 178 179 180 181 |
# File 'lib/eth/abi/type.rb', line 169 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 |