aboutsummaryrefslogtreecommitdiffstats
path: root/accounts/abi/bind/bind.go
diff options
context:
space:
mode:
Diffstat (limited to 'accounts/abi/bind/bind.go')
-rw-r--r--accounts/abi/bind/bind.go169
1 files changed, 99 insertions, 70 deletions
diff --git a/accounts/abi/bind/bind.go b/accounts/abi/bind/bind.go
index e31b45481..7fdd2c624 100644
--- a/accounts/abi/bind/bind.go
+++ b/accounts/abi/bind/bind.go
@@ -164,118 +164,147 @@ var bindType = map[Lang]func(kind abi.Type) string{
LangJava: bindTypeJava,
}
+// Helper function for the binding generators.
+// It reads the unmatched characters after the inner type-match,
+// (since the inner type is a prefix of the total type declaration),
+// looks for valid arrays (possibly a dynamic one) wrapping the inner type,
+// and returns the sizes of these arrays.
+//
+// Returned array sizes are in the same order as solidity signatures; inner array size first.
+// Array sizes may also be "", indicating a dynamic array.
+func wrapArray(stringKind string, innerLen int, innerMapping string) (string, []string) {
+ remainder := stringKind[innerLen:]
+ //find all the sizes
+ matches := regexp.MustCompile(`\[(\d*)\]`).FindAllStringSubmatch(remainder, -1)
+ parts := make([]string, 0, len(matches))
+ for _, match := range matches {
+ //get group 1 from the regex match
+ parts = append(parts, match[1])
+ }
+ return innerMapping, parts
+}
+
+// Translates the array sizes to a Go-lang declaration of a (nested) array of the inner type.
+// Simply returns the inner type if arraySizes is empty.
+func arrayBindingGo(inner string, arraySizes []string) string {
+ out := ""
+ //prepend all array sizes, from outer (end arraySizes) to inner (start arraySizes)
+ for i := len(arraySizes) - 1; i >= 0; i-- {
+ out += "[" + arraySizes[i] + "]"
+ }
+ out += inner
+ return out
+}
+
// bindTypeGo converts a Solidity type to a Go one. Since there is no clear mapping
// from all Solidity types to Go ones (e.g. uint17), those that cannot be exactly
// mapped will use an upscaled type (e.g. *big.Int).
func bindTypeGo(kind abi.Type) string {
stringKind := kind.String()
+ innerLen, innerMapping := bindUnnestedTypeGo(stringKind)
+ return arrayBindingGo(wrapArray(stringKind, innerLen, innerMapping))
+}
+
+// The inner function of bindTypeGo, this finds the inner type of stringKind.
+// (Or just the type itself if it is not an array or slice)
+// The length of the matched part is returned, with the the translated type.
+func bindUnnestedTypeGo(stringKind string) (int, string) {
switch {
case strings.HasPrefix(stringKind, "address"):
- parts := regexp.MustCompile(`address(\[[0-9]*\])?`).FindStringSubmatch(stringKind)
- if len(parts) != 2 {
- return stringKind
- }
- return fmt.Sprintf("%scommon.Address", parts[1])
+ return len("address"), "common.Address"
case strings.HasPrefix(stringKind, "bytes"):
- parts := regexp.MustCompile(`bytes([0-9]*)(\[[0-9]*\])?`).FindStringSubmatch(stringKind)
- if len(parts) != 3 {
- return stringKind
- }
- return fmt.Sprintf("%s[%s]byte", parts[2], parts[1])
+ parts := regexp.MustCompile(`bytes([0-9]*)`).FindStringSubmatch(stringKind)
+ return len(parts[0]), fmt.Sprintf("[%s]byte", parts[1])
case strings.HasPrefix(stringKind, "int") || strings.HasPrefix(stringKind, "uint"):
- parts := regexp.MustCompile(`(u)?int([0-9]*)(\[[0-9]*\])?`).FindStringSubmatch(stringKind)
- if len(parts) != 4 {
- return stringKind
- }
+ parts := regexp.MustCompile(`(u)?int([0-9]*)`).FindStringSubmatch(stringKind)
switch parts[2] {
case "8", "16", "32", "64":
- return fmt.Sprintf("%s%sint%s", parts[3], parts[1], parts[2])
+ return len(parts[0]), fmt.Sprintf("%sint%s", parts[1], parts[2])
}
- return fmt.Sprintf("%s*big.Int", parts[3])
+ return len(parts[0]), "*big.Int"
- case strings.HasPrefix(stringKind, "bool") || strings.HasPrefix(stringKind, "string"):
- parts := regexp.MustCompile(`([a-z]+)(\[[0-9]*\])?`).FindStringSubmatch(stringKind)
- if len(parts) != 3 {
- return stringKind
- }
- return fmt.Sprintf("%s%s", parts[2], parts[1])
+ case strings.HasPrefix(stringKind, "bool"):
+ return len("bool"), "bool"
+
+ case strings.HasPrefix(stringKind, "string"):
+ return len("string"), "string"
default:
- return stringKind
+ return len(stringKind), stringKind
}
}
+// Translates the array sizes to a Java declaration of a (nested) array of the inner type.
+// Simply returns the inner type if arraySizes is empty.
+func arrayBindingJava(inner string, arraySizes []string) string {
+ // Java array type declarations do not include the length.
+ return inner + strings.Repeat("[]", len(arraySizes))
+}
+
// bindTypeJava converts a Solidity type to a Java one. Since there is no clear mapping
// from all Solidity types to Java ones (e.g. uint17), those that cannot be exactly
// mapped will use an upscaled type (e.g. BigDecimal).
func bindTypeJava(kind abi.Type) string {
stringKind := kind.String()
+ innerLen, innerMapping := bindUnnestedTypeJava(stringKind)
+ return arrayBindingJava(wrapArray(stringKind, innerLen, innerMapping))
+}
+
+// The inner function of bindTypeJava, this finds the inner type of stringKind.
+// (Or just the type itself if it is not an array or slice)
+// The length of the matched part is returned, with the the translated type.
+func bindUnnestedTypeJava(stringKind string) (int, string) {
switch {
case strings.HasPrefix(stringKind, "address"):
parts := regexp.MustCompile(`address(\[[0-9]*\])?`).FindStringSubmatch(stringKind)
if len(parts) != 2 {
- return stringKind
+ return len(stringKind), stringKind
}
if parts[1] == "" {
- return fmt.Sprintf("Address")
+ return len("address"), "Address"
}
- return fmt.Sprintf("Addresses")
+ return len(parts[0]), "Addresses"
case strings.HasPrefix(stringKind, "bytes"):
- parts := regexp.MustCompile(`bytes([0-9]*)(\[[0-9]*\])?`).FindStringSubmatch(stringKind)
- if len(parts) != 3 {
- return stringKind
- }
- if parts[2] != "" {
- return "byte[][]"
+ parts := regexp.MustCompile(`bytes([0-9]*)`).FindStringSubmatch(stringKind)
+ if len(parts) != 2 {
+ return len(stringKind), stringKind
}
- return "byte[]"
+ return len(parts[0]), "byte[]"
case strings.HasPrefix(stringKind, "int") || strings.HasPrefix(stringKind, "uint"):
- parts := regexp.MustCompile(`(u)?int([0-9]*)(\[[0-9]*\])?`).FindStringSubmatch(stringKind)
- if len(parts) != 4 {
- return stringKind
- }
- switch parts[2] {
- case "8", "16", "32", "64":
- if parts[1] == "" {
- if parts[3] == "" {
- return fmt.Sprintf("int%s", parts[2])
- }
- return fmt.Sprintf("int%s[]", parts[2])
- }
+ //Note that uint and int (without digits) are also matched,
+ // these are size 256, and will translate to BigInt (the default).
+ parts := regexp.MustCompile(`(u)?int([0-9]*)`).FindStringSubmatch(stringKind)
+ if len(parts) != 3 {
+ return len(stringKind), stringKind
}
- if parts[3] == "" {
- return fmt.Sprintf("BigInt")
+
+ namedSize := map[string]string{
+ "8": "byte",
+ "16": "short",
+ "32": "int",
+ "64": "long",
+ }[parts[2]]
+
+ //default to BigInt
+ if namedSize == "" {
+ namedSize = "BigInt"
}
- return fmt.Sprintf("BigInts")
+ return len(parts[0]), namedSize
case strings.HasPrefix(stringKind, "bool"):
- parts := regexp.MustCompile(`bool(\[[0-9]*\])?`).FindStringSubmatch(stringKind)
- if len(parts) != 2 {
- return stringKind
- }
- if parts[1] == "" {
- return fmt.Sprintf("bool")
- }
- return fmt.Sprintf("bool[]")
+ return len("bool"), "boolean"
case strings.HasPrefix(stringKind, "string"):
- parts := regexp.MustCompile(`string(\[[0-9]*\])?`).FindStringSubmatch(stringKind)
- if len(parts) != 2 {
- return stringKind
- }
- if parts[1] == "" {
- return fmt.Sprintf("String")
- }
- return fmt.Sprintf("String[]")
+ return len("string"), "String"
default:
- return stringKind
+ return len(stringKind), stringKind
}
}
@@ -325,11 +354,13 @@ func namedTypeJava(javaKind string, solKind abi.Type) string {
return "String"
case "string[]":
return "Strings"
- case "bool":
+ case "boolean":
return "Bool"
- case "bool[]":
+ case "boolean[]":
return "Bools"
- case "BigInt":
+ case "BigInt[]":
+ return "BigInts"
+ default:
parts := regexp.MustCompile(`(u)?int([0-9]*)(\[[0-9]*\])?`).FindStringSubmatch(solKind.String())
if len(parts) != 4 {
return javaKind
@@ -344,8 +375,6 @@ func namedTypeJava(javaKind string, solKind abi.Type) string {
default:
return javaKind
}
- default:
- return javaKind
}
}