github.com/n1ghtfa1l/go-vnt@v0.6.4-alpha.6/accounts/abi/key.go (about)

     1  // Copyright 2019 The go-vnt Authors
     2  // This file is part of the go-vnt library.
     3  //
     4  // The go-vnt library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-vnt library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-vnt library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package abi
    18  
    19  import (
    20  	"fmt"
    21  	"strings"
    22  )
    23  
    24  type StorageType uint64
    25  
    26  const (
    27  	NormalTy StorageType = iota
    28  	MappingKeyTy
    29  	ArrayIndexTy
    30  	MappingValueTy
    31  	ArrayValueTy
    32  	StructValueTy
    33  	LengthTy
    34  )
    35  
    36  const (
    37  	TY_INT32 int32 = 1 + iota
    38  	TY_INT64
    39  	TY_UINT32
    40  	TY_UINT64
    41  	TY_UINT256
    42  	TY_STRING
    43  	TY_ADDRESS
    44  	TY_BOOL
    45  	TY_POINTER
    46  )
    47  
    48  type Key struct {
    49  	Name      string           `json:"name"`
    50  	Tables    Tables           `json:"tables"`
    51  	Types     map[string]Type  `json:"-"`
    52  	Keys      map[string]Table `json:"keys"`
    53  	Connector map[string][]string
    54  }
    55  
    56  type Connector struct {
    57  	Name string
    58  	Type string
    59  }
    60  
    61  func errnotexist(name string) error {
    62  	return fmt.Errorf("Can not find name %s", name)
    63  }
    64  
    65  type Root struct {
    66  	Root map[string]*Node
    67  }
    68  
    69  type Node struct {
    70  	FieldName     string           `json:"name"`
    71  	FieldType     string           `json:"type"`
    72  	FieldLocation string           `json:"-"`
    73  	StorageType   StorageType      `json:"storagetype"`
    74  	Children      map[string]*Node `json:"children"`
    75  	Tables        []*Node          `json:"tables"`
    76  }
    77  
    78  func NewNode(fieldname string, fieldtype string, fieldlocation string) *Node {
    79  	return &Node{
    80  		FieldName:     fieldname,
    81  		FieldType:     fieldtype,
    82  		FieldLocation: fieldlocation,
    83  		Children:      make(map[string]*Node),
    84  		Tables:        []*Node{},
    85  	}
    86  }
    87  
    88  func (nd *Node) addchild(fieldname, fieldtype, fieldlocation, base string) *Node {
    89  	child, ok := nd.Children[base]
    90  	if !ok {
    91  		child = NewNode(fieldname, fieldtype, fieldlocation)
    92  		nd.Children[fieldname] = child
    93  		if child.FieldName != "mapping1537182776" && child.FieldName != "array1537182776" {
    94  			nd.Tables = append(nd.Tables, child)
    95  		}
    96  
    97  	}
    98  	return child
    99  }
   100  
   101  func (nd *Node) Add(fieldname string, fieldtype string, fieldlocation string, base string) *Node {
   102  	return nd.addchild(fieldname, fieldtype, fieldlocation, base)
   103  }
   104  
   105  func (nd *Node) Get(name string) (*Node, error) {
   106  	if _, ok := nd.Children[name]; !ok {
   107  		return &Node{}, errnotexist(name)
   108  	}
   109  	return nd, nil
   110  }
   111  
   112  func (nd *Node) Traversal(r Root) {
   113  	// fmt.Printf("Node %v\n", nd)
   114  	for _, v := range nd.Children {
   115  		if child, ok := r.Root[v.FieldType]; ok {
   116  
   117  			if v.FieldType != child.FieldType {
   118  				if child1, ok := r.Root[child.FieldType]; ok {
   119  					child = child1
   120  				}
   121  			}
   122  			v.FieldType = ""
   123  			cld := make(map[string]*Node)
   124  			tables := []*Node{}
   125  			for k, c := range child.Children {
   126  				cld[k] = c
   127  
   128  				if k != "mapping1537182776" && k != "array1537182776" {
   129  					tables = append(tables, c)
   130  				}
   131  			}
   132  
   133  			v.Children = cld
   134  			v.Tables = tables
   135  
   136  			//todo 优化 clang.go:204
   137  			var allkey = ""
   138  			for k, _ := range v.Children {
   139  				allkey = allkey + k
   140  			}
   141  			if strings.Contains(allkey, "mapping1537182776") {
   142  				v.FieldType = "mapping"
   143  			} else if strings.Contains(allkey, "array1537182776") {
   144  				v.FieldType = "array"
   145  			} else {
   146  				v.FieldType = "struct"
   147  			}
   148  
   149  			for k, c := range child.Children {
   150  				if v.FieldType == "mapping" {
   151  					if k == "key" {
   152  						c.StorageType = MappingKeyTy
   153  					} else if k == "value" {
   154  						c.StorageType = MappingValueTy
   155  					} else {
   156  						delete(v.Children, k)
   157  					}
   158  				} else if v.FieldType == "array" {
   159  					if k == "index" {
   160  						c.StorageType = ArrayIndexTy
   161  					} else if k == "value" {
   162  						c.StorageType = ArrayValueTy
   163  					} else if k == "length" {
   164  						c.StorageType = LengthTy
   165  					} else {
   166  						delete(v.Children, k)
   167  					}
   168  				} else if v.FieldType == "struct" {
   169  					c.StorageType = StructValueTy
   170  				}
   171  			}
   172  
   173  			v.Traversal(r)
   174  		}
   175  
   176  	}
   177  }
   178  
   179  func (r Root) Fulling() Root {
   180  	for _, v := range r.Root {
   181  		v.Traversal(r)
   182  	}
   183  	return r
   184  }
   185  
   186  func (key *Key) KeyTraversal() {
   187  	if key.Types == nil {
   188  		key.Types = make(map[string]Type)
   189  	}
   190  	if key.Keys == nil {
   191  		key.Keys = make(map[string]Table)
   192  	}
   193  	for _, v := range key.Tables {
   194  		v.Traversal(key.Name, key)
   195  	}
   196  }
   197  
   198  func KeyType(tp string) int32 {
   199  	switch tp {
   200  	case "int32":
   201  		return TY_INT32
   202  	case "int64":
   203  		return TY_INT64
   204  	case "uint32":
   205  		return TY_UINT32
   206  	case "uint64":
   207  		return TY_UINT64
   208  	case "uint256":
   209  		return TY_UINT256
   210  	case "string":
   211  		return TY_STRING
   212  	case "address":
   213  		return TY_ADDRESS
   214  	case "bool", "_Bool": //support stdbool.h
   215  		return TY_BOOL
   216  	case "pointer":
   217  		return TY_POINTER
   218  	default:
   219  		panic(fmt.Sprintf("Error: Unsupport Type %s", tp))
   220  	}
   221  }