Skip to content

Commit 6069b1a

Browse files
rjl493456442karalabe
authored andcommitted
mobile: fix mobile interface (#19180)
* mobile: fix mobile interface * mobile, accounts: generate correct java binding * accounts: fix java type binding * mobile: support integer slice * accounts/abi/bind, cmd/abigen: implement java binding tests
1 parent fd072c2 commit 6069b1a

File tree

9 files changed

+903
-233
lines changed

9 files changed

+903
-233
lines changed

accounts/abi/bind/bind.go

Lines changed: 82 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ type Lang int
3838
const (
3939
LangGo Lang = iota
4040
LangJava
41-
LangObjC
4241
)
4342

4443
// Bind generates a Go wrapper around a contract ABI. This wrapper isn't meant
@@ -164,124 +163,62 @@ var bindType = map[Lang]func(kind abi.Type) string{
164163
LangJava: bindTypeJava,
165164
}
166165

167-
// Helper function for the binding generators.
168-
// It reads the unmatched characters after the inner type-match,
169-
// (since the inner type is a prefix of the total type declaration),
170-
// looks for valid arrays (possibly a dynamic one) wrapping the inner type,
171-
// and returns the sizes of these arrays.
172-
//
173-
// Returned array sizes are in the same order as solidity signatures; inner array size first.
174-
// Array sizes may also be "", indicating a dynamic array.
175-
func wrapArray(stringKind string, innerLen int, innerMapping string) (string, []string) {
176-
remainder := stringKind[innerLen:]
177-
//find all the sizes
178-
matches := regexp.MustCompile(`\[(\d*)\]`).FindAllStringSubmatch(remainder, -1)
179-
parts := make([]string, 0, len(matches))
180-
for _, match := range matches {
181-
//get group 1 from the regex match
182-
parts = append(parts, match[1])
183-
}
184-
return innerMapping, parts
185-
}
186-
187-
// Translates the array sizes to a Go-lang declaration of a (nested) array of the inner type.
188-
// Simply returns the inner type if arraySizes is empty.
189-
func arrayBindingGo(inner string, arraySizes []string) string {
190-
out := ""
191-
//prepend all array sizes, from outer (end arraySizes) to inner (start arraySizes)
192-
for i := len(arraySizes) - 1; i >= 0; i-- {
193-
out += "[" + arraySizes[i] + "]"
194-
}
195-
out += inner
196-
return out
197-
}
198-
199-
// bindTypeGo converts a Solidity type to a Go one. Since there is no clear mapping
200-
// from all Solidity types to Go ones (e.g. uint17), those that cannot be exactly
201-
// mapped will use an upscaled type (e.g. *big.Int).
202-
func bindTypeGo(kind abi.Type) string {
203-
stringKind := kind.String()
204-
innerLen, innerMapping := bindUnnestedTypeGo(stringKind)
205-
return arrayBindingGo(wrapArray(stringKind, innerLen, innerMapping))
206-
}
207-
208-
// The inner function of bindTypeGo, this finds the inner type of stringKind.
209-
// (Or just the type itself if it is not an array or slice)
210-
// The length of the matched part is returned, with the translated type.
211-
func bindUnnestedTypeGo(stringKind string) (int, string) {
212-
213-
switch {
214-
case strings.HasPrefix(stringKind, "address"):
215-
return len("address"), "common.Address"
216-
217-
case strings.HasPrefix(stringKind, "bytes"):
218-
parts := regexp.MustCompile(`bytes([0-9]*)`).FindStringSubmatch(stringKind)
219-
return len(parts[0]), fmt.Sprintf("[%s]byte", parts[1])
220-
221-
case strings.HasPrefix(stringKind, "int") || strings.HasPrefix(stringKind, "uint"):
222-
parts := regexp.MustCompile(`(u)?int([0-9]*)`).FindStringSubmatch(stringKind)
166+
// bindBasicTypeGo converts basic solidity types(except array, slice and tuple) to Go one.
167+
func bindBasicTypeGo(kind abi.Type) string {
168+
switch kind.T {
169+
case abi.AddressTy:
170+
return "common.Address"
171+
case abi.IntTy, abi.UintTy:
172+
parts := regexp.MustCompile(`(u)?int([0-9]*)`).FindStringSubmatch(kind.String())
223173
switch parts[2] {
224174
case "8", "16", "32", "64":
225-
return len(parts[0]), fmt.Sprintf("%sint%s", parts[1], parts[2])
175+
return fmt.Sprintf("%sint%s", parts[1], parts[2])
226176
}
227-
return len(parts[0]), "*big.Int"
228-
229-
case strings.HasPrefix(stringKind, "bool"):
230-
return len("bool"), "bool"
231-
232-
case strings.HasPrefix(stringKind, "string"):
233-
return len("string"), "string"
234-
177+
return "*big.Int"
178+
case abi.FixedBytesTy:
179+
return fmt.Sprintf("[%d]byte", kind.Size)
180+
case abi.BytesTy:
181+
return "[]byte"
182+
case abi.FunctionTy:
183+
// todo(rjl493456442)
184+
return ""
235185
default:
236-
return len(stringKind), stringKind
186+
// string, bool types
187+
return kind.String()
237188
}
238189
}
239190

240-
// Translates the array sizes to a Java declaration of a (nested) array of the inner type.
241-
// Simply returns the inner type if arraySizes is empty.
242-
func arrayBindingJava(inner string, arraySizes []string) string {
243-
// Java array type declarations do not include the length.
244-
return inner + strings.Repeat("[]", len(arraySizes))
245-
}
246-
247-
// bindTypeJava converts a Solidity type to a Java one. Since there is no clear mapping
248-
// from all Solidity types to Java ones (e.g. uint17), those that cannot be exactly
191+
// bindTypeGo converts solidity types to Go ones. Since there is no clear mapping
192+
// from all Solidity types to Go ones (e.g. uint17), those that cannot be exactly
249193
// mapped will use an upscaled type (e.g. BigDecimal).
250-
func bindTypeJava(kind abi.Type) string {
251-
stringKind := kind.String()
252-
innerLen, innerMapping := bindUnnestedTypeJava(stringKind)
253-
return arrayBindingJava(wrapArray(stringKind, innerLen, innerMapping))
194+
func bindTypeGo(kind abi.Type) string {
195+
// todo(rjl493456442) tuple
196+
switch kind.T {
197+
case abi.ArrayTy:
198+
return fmt.Sprintf("[%d]", kind.Size) + bindTypeGo(*kind.Elem)
199+
case abi.SliceTy:
200+
return "[]" + bindTypeGo(*kind.Elem)
201+
default:
202+
return bindBasicTypeGo(kind)
203+
}
254204
}
255205

256-
// The inner function of bindTypeJava, this finds the inner type of stringKind.
257-
// (Or just the type itself if it is not an array or slice)
258-
// The length of the matched part is returned, with the translated type.
259-
func bindUnnestedTypeJava(stringKind string) (int, string) {
260-
261-
switch {
262-
case strings.HasPrefix(stringKind, "address"):
263-
parts := regexp.MustCompile(`address(\[[0-9]*\])?`).FindStringSubmatch(stringKind)
264-
if len(parts) != 2 {
265-
return len(stringKind), stringKind
266-
}
267-
if parts[1] == "" {
268-
return len("address"), "Address"
269-
}
270-
return len(parts[0]), "Addresses"
271-
272-
case strings.HasPrefix(stringKind, "bytes"):
273-
parts := regexp.MustCompile(`bytes([0-9]*)`).FindStringSubmatch(stringKind)
274-
if len(parts) != 2 {
275-
return len(stringKind), stringKind
276-
}
277-
return len(parts[0]), "byte[]"
278-
279-
case strings.HasPrefix(stringKind, "int") || strings.HasPrefix(stringKind, "uint"):
280-
//Note that uint and int (without digits) are also matched,
206+
// bindBasicTypeJava converts basic solidity types(except array, slice and tuple) to Java one.
207+
func bindBasicTypeJava(kind abi.Type) string {
208+
switch kind.T {
209+
case abi.AddressTy:
210+
return "Address"
211+
case abi.IntTy, abi.UintTy:
212+
// Note that uint and int (without digits) are also matched,
281213
// these are size 256, and will translate to BigInt (the default).
282-
parts := regexp.MustCompile(`(u)?int([0-9]*)`).FindStringSubmatch(stringKind)
214+
parts := regexp.MustCompile(`(u)?int([0-9]*)`).FindStringSubmatch(kind.String())
283215
if len(parts) != 3 {
284-
return len(stringKind), stringKind
216+
return kind.String()
217+
}
218+
// All unsigned integers should be translated to BigInt since gomobile doesn't
219+
// support them.
220+
if parts[1] == "u" {
221+
return "BigInt"
285222
}
286223

287224
namedSize := map[string]string{
@@ -291,20 +228,48 @@ func bindUnnestedTypeJava(stringKind string) (int, string) {
291228
"64": "long",
292229
}[parts[2]]
293230

294-
//default to BigInt
231+
// default to BigInt
295232
if namedSize == "" {
296233
namedSize = "BigInt"
297234
}
298-
return len(parts[0]), namedSize
299-
300-
case strings.HasPrefix(stringKind, "bool"):
301-
return len("bool"), "boolean"
302-
303-
case strings.HasPrefix(stringKind, "string"):
304-
return len("string"), "String"
235+
return namedSize
236+
case abi.FixedBytesTy, abi.BytesTy:
237+
return "byte[]"
238+
case abi.BoolTy:
239+
return "boolean"
240+
case abi.StringTy:
241+
return "String"
242+
case abi.FunctionTy:
243+
// todo(rjl493456442)
244+
return ""
245+
default:
246+
return kind.String()
247+
}
248+
}
305249

250+
// bindTypeJava converts a Solidity type to a Java one. Since there is no clear mapping
251+
// from all Solidity types to Java ones (e.g. uint17), those that cannot be exactly
252+
// mapped will use an upscaled type (e.g. BigDecimal).
253+
func bindTypeJava(kind abi.Type) string {
254+
switch kind.T {
255+
case abi.ArrayTy, abi.SliceTy:
256+
// Explicitly convert multidimensional types to predefined type in go side.
257+
inner := bindTypeJava(*kind.Elem)
258+
switch inner {
259+
case "boolean":
260+
return "Bools"
261+
case "String":
262+
return "Strings"
263+
case "Address":
264+
return "Addresses"
265+
case "byte[]":
266+
return "Binaries"
267+
case "BigInt":
268+
return "BigInts"
269+
}
270+
return inner + "[]"
306271
default:
307-
return len(stringKind), stringKind
272+
return bindBasicTypeJava(kind)
308273
}
309274
}
310275

@@ -329,7 +294,7 @@ func bindTopicTypeGo(kind abi.Type) string {
329294
// funcionality as for simple types, but dynamic types get converted to hashes.
330295
func bindTopicTypeJava(kind abi.Type) string {
331296
bound := bindTypeJava(kind)
332-
if bound == "String" || bound == "Bytes" {
297+
if bound == "String" || bound == "byte[]" {
333298
bound = "Hash"
334299
}
335300
return bound
@@ -348,18 +313,8 @@ func namedTypeJava(javaKind string, solKind abi.Type) string {
348313
switch javaKind {
349314
case "byte[]":
350315
return "Binary"
351-
case "byte[][]":
352-
return "Binaries"
353-
case "string":
354-
return "String"
355-
case "string[]":
356-
return "Strings"
357316
case "boolean":
358317
return "Bool"
359-
case "boolean[]":
360-
return "Bools"
361-
case "BigInt[]":
362-
return "BigInts"
363318
default:
364319
parts := regexp.MustCompile(`(u)?int([0-9]*)(\[[0-9]*\])?`).FindStringSubmatch(solKind.String())
365320
if len(parts) != 4 {

accounts/abi/bind/bind_test.go

Lines changed: 398 additions & 1 deletion
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)