| 
									
										
										
										
											2016-04-07 11:39:22 +02:00
										 |  |  | // Copyright 2016 The go-ethereum Authors | 
					
						
							|  |  |  | // This file is part of the go-ethereum library. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // The go-ethereum library is free software: you can redistribute it and/or modify | 
					
						
							|  |  |  | // it under the terms of the GNU Lesser General Public License as published by | 
					
						
							|  |  |  | // the Free Software Foundation, either version 3 of the License, or | 
					
						
							|  |  |  | // (at your option) any later version. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // The go-ethereum library is distributed in the hope that it will be useful, | 
					
						
							|  |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 
					
						
							|  |  |  | // GNU Lesser General Public License for more details. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // You should have received a copy of the GNU Lesser General Public License | 
					
						
							|  |  |  | // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | package abi | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2017-06-27 03:05:33 -05:00
										 |  |  | 	"errors" | 
					
						
							| 
									
										
										
										
											2016-04-07 11:39:22 +02:00
										 |  |  | 	"fmt" | 
					
						
							|  |  |  | 	"reflect" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-27 03:05:33 -05:00
										 |  |  | var ( | 
					
						
							|  |  |  | 	errBadBool = errors.New("abi: improperly encoded boolean value") | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-07 11:39:22 +02:00
										 |  |  | // formatSliceString formats the reflection kind with the given slice size | 
					
						
							|  |  |  | // and returns a formatted string representation. | 
					
						
							|  |  |  | func formatSliceString(kind reflect.Kind, sliceSize int) string { | 
					
						
							|  |  |  | 	if sliceSize == -1 { | 
					
						
							|  |  |  | 		return fmt.Sprintf("[]%v", kind) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return fmt.Sprintf("[%d]%v", sliceSize, kind) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // sliceTypeCheck checks that the given slice can by assigned to the reflection | 
					
						
							|  |  |  | // type in t. | 
					
						
							|  |  |  | func sliceTypeCheck(t Type, val reflect.Value) error { | 
					
						
							| 
									
										
										
										
											2016-04-20 21:30:02 +02:00
										 |  |  | 	if val.Kind() != reflect.Slice && val.Kind() != reflect.Array { | 
					
						
							| 
									
										
										
										
											2017-10-17 06:07:08 -05:00
										 |  |  | 		return typeErr(formatSliceString(t.Kind, t.Size), val.Type()) | 
					
						
							| 
									
										
										
										
											2016-04-07 11:39:22 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-10-17 06:07:08 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if t.T == ArrayTy && val.Len() != t.Size { | 
					
						
							|  |  |  | 		return typeErr(formatSliceString(t.Elem.Kind, t.Size), formatSliceString(val.Type().Elem().Kind(), val.Len())) | 
					
						
							| 
									
										
										
										
											2016-04-07 11:39:22 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-17 06:07:08 -05:00
										 |  |  | 	if t.Elem.T == SliceTy { | 
					
						
							| 
									
										
										
										
											2016-04-07 11:39:22 +02:00
										 |  |  | 		if val.Len() > 0 { | 
					
						
							|  |  |  | 			return sliceTypeCheck(*t.Elem, val.Index(0)) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-10-17 06:07:08 -05:00
										 |  |  | 	} else if t.Elem.T == ArrayTy { | 
					
						
							| 
									
										
										
										
											2016-04-07 11:39:22 +02:00
										 |  |  | 		return sliceTypeCheck(*t.Elem, val.Index(0)) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-20 21:30:02 +02:00
										 |  |  | 	if elemKind := val.Type().Elem().Kind(); elemKind != t.Elem.Kind { | 
					
						
							| 
									
										
										
										
											2017-10-17 06:07:08 -05:00
										 |  |  | 		return typeErr(formatSliceString(t.Elem.Kind, t.Size), val.Type()) | 
					
						
							| 
									
										
										
										
											2016-04-07 11:39:22 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-20 21:30:02 +02:00
										 |  |  | // typeCheck checks that the given reflection value can be assigned to the reflection | 
					
						
							| 
									
										
										
										
											2016-04-07 11:39:22 +02:00
										 |  |  | // type in t. | 
					
						
							|  |  |  | func typeCheck(t Type, value reflect.Value) error { | 
					
						
							| 
									
										
										
										
											2017-10-17 06:07:08 -05:00
										 |  |  | 	if t.T == SliceTy || t.T == ArrayTy { | 
					
						
							| 
									
										
										
										
											2016-04-07 11:39:22 +02:00
										 |  |  | 		return sliceTypeCheck(t, value) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Check base type validity. Element types will be checked later on. | 
					
						
							|  |  |  | 	if t.Kind != value.Kind() { | 
					
						
							|  |  |  | 		return typeErr(t.Kind, value.Kind()) | 
					
						
							| 
									
										
										
										
											2017-10-17 06:07:08 -05:00
										 |  |  | 	} else if t.T == FixedBytesTy && t.Size != value.Len() { | 
					
						
							|  |  |  | 		return typeErr(t.Type, value.Type()) | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		return nil | 
					
						
							| 
									
										
										
										
											2016-04-07 11:39:22 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // typeErr returns a formatted type casting error. | 
					
						
							|  |  |  | func typeErr(expected, got interface{}) error { | 
					
						
							|  |  |  | 	return fmt.Errorf("abi: cannot use %v as type %v as argument", got, expected) | 
					
						
							|  |  |  | } |