accounts/abi: Modified unpackAtomic to accept struct lvalues
This commit is contained in:
		
							parent
							
								
									13b566e06e
								
							
						
					
					
						commit
						60a999f238
					
				| @ -86,7 +86,7 @@ func (abi ABI) Unpack(v interface{}, name string, output []byte) (err error) { | ||||
| 		} | ||||
| 		return method.Outputs.Unpack(v, output) | ||||
| 	} else if event, ok := abi.Events[name]; ok { | ||||
| 		return event.Inputs.unpackTuple(v, output) | ||||
| 		return event.Inputs.Unpack(v, output) | ||||
| 	} | ||||
| 	return fmt.Errorf("abi: could not locate named method or event") | ||||
| } | ||||
|  | ||||
| @ -113,16 +113,8 @@ func (arguments Arguments) unpackTuple(v interface{}, marshalledValues []interfa | ||||
| 	} | ||||
| 	// If the output interface is a struct, make sure names don't collide
 | ||||
| 	if kind == reflect.Struct { | ||||
| 		exists := make(map[string]bool) | ||||
| 		for _, arg := range arguments { | ||||
| 			field := capitalise(arg.Name) | ||||
| 			if field == "" { | ||||
| 				return fmt.Errorf("abi: purely underscored output cannot unpack to struct") | ||||
| 			} | ||||
| 			if exists[field] { | ||||
| 				return fmt.Errorf("abi: multiple outputs mapping to the same struct field '%s'", field) | ||||
| 			} | ||||
| 			exists[field] = true | ||||
| 		if err := requireUniqueStructFieldNames(arguments); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	for i, arg := range arguments.NonIndexed() { | ||||
| @ -131,15 +123,10 @@ func (arguments Arguments) unpackTuple(v interface{}, marshalledValues []interfa | ||||
| 
 | ||||
| 		switch kind { | ||||
| 		case reflect.Struct: | ||||
| 			name := capitalise(arg.Name) | ||||
| 			for j := 0; j < typ.NumField(); j++ { | ||||
| 				// TODO read tags: `abi:"fieldName"`
 | ||||
| 				if typ.Field(j).Name == name { | ||||
| 					if err := set(value.Field(j), reflectValue, arg); err != nil { | ||||
| 			err := unpackStruct(value, reflectValue, arg) | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 				} | ||||
| 			} | ||||
| 		case reflect.Slice, reflect.Array: | ||||
| 			if value.Len() < i { | ||||
| 				return fmt.Errorf("abi: insufficient number of arguments for unpack, want %d, got %d", len(arguments), value.Len()) | ||||
| @ -165,8 +152,20 @@ func (arguments Arguments) unpackAtomic(v interface{}, marshalledValues []interf | ||||
| 		return fmt.Errorf("abi: wrong length, expected single value, got %d", len(marshalledValues)) | ||||
| 	} | ||||
| 	elem := reflect.ValueOf(v).Elem() | ||||
| 	kind := elem.Kind() | ||||
| 	reflectValue := reflect.ValueOf(marshalledValues[0]) | ||||
| 
 | ||||
| 	if kind == reflect.Struct { | ||||
| 		//make sure names don't collide
 | ||||
| 		if err := requireUniqueStructFieldNames(arguments); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 
 | ||||
| 		return unpackStruct(elem, reflectValue, arguments[0]) | ||||
| 	} | ||||
| 
 | ||||
| 	return set(elem, reflectValue, arguments.NonIndexed()[0]) | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| // Computes the full size of an array;
 | ||||
| @ -278,3 +277,18 @@ func capitalise(input string) string { | ||||
| 	} | ||||
| 	return strings.ToUpper(input[:1]) + input[1:] | ||||
| } | ||||
| 
 | ||||
| //unpackStruct extracts each argument into its corresponding struct field
 | ||||
| func unpackStruct(value, reflectValue reflect.Value, arg Argument) error { | ||||
| 	name := capitalise(arg.Name) | ||||
| 	typ := value.Type() | ||||
| 	for j := 0; j < typ.NumField(); j++ { | ||||
| 		// TODO read tags: `abi:"fieldName"`
 | ||||
| 		if typ.Field(j).Name == name { | ||||
| 			if err := set(value.Field(j), reflectValue, arg); err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| @ -110,3 +110,19 @@ func requireUnpackKind(v reflect.Value, t reflect.Type, k reflect.Kind, | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // requireUniqueStructFieldNames makes sure field names don't collide
 | ||||
| func requireUniqueStructFieldNames(args Arguments) error { | ||||
| 	exists := make(map[string]bool) | ||||
| 	for _, arg := range args { | ||||
| 		field := capitalise(arg.Name) | ||||
| 		if field == "" { | ||||
| 			return fmt.Errorf("abi: purely underscored output cannot unpack to struct") | ||||
| 		} | ||||
| 		if exists[field] { | ||||
| 			return fmt.Errorf("abi: multiple outputs mapping to the same struct field '%s'", field) | ||||
| 		} | ||||
| 		exists[field] = true | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user