github.com/haliliceylan/bsc@v1.1.10-0.20220501224556-eb78d644ebcb/rlp/typecache.go (about)

     1  // Copyright 2014 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum 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-ethereum 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-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package rlp
    18  
    19  import (
    20  	"fmt"
    21  	"reflect"
    22  	"strings"
    23  	"sync"
    24  	"sync/atomic"
    25  )
    26  
    27  // typeinfo is an entry in the type cache.
    28  type typeinfo struct {
    29  	decoder    decoder
    30  	decoderErr error // error from makeDecoder
    31  	writer     writer
    32  	writerErr  error // error from makeWriter
    33  }
    34  
    35  // tags represents struct tags.
    36  type tags struct {
    37  	// rlp:"nil" controls whether empty input results in a nil pointer.
    38  	// nilKind is the kind of empty value allowed for the field.
    39  	nilKind Kind
    40  	nilOK   bool
    41  
    42  	// rlp:"optional" allows for a field to be missing in the input list.
    43  	// If this is set, all subsequent fields must also be optional.
    44  	optional bool
    45  
    46  	// rlp:"tail" controls whether this field swallows additional list elements. It can
    47  	// only be set for the last field, which must be of slice type.
    48  	tail bool
    49  
    50  	// rlp:"-" ignores fields.
    51  	ignored bool
    52  }
    53  
    54  // typekey is the key of a type in typeCache. It includes the struct tags because
    55  // they might generate a different decoder.
    56  type typekey struct {
    57  	reflect.Type
    58  	tags
    59  }
    60  
    61  type decoder func(*Stream, reflect.Value) error
    62  
    63  type writer func(reflect.Value, *encbuf) error
    64  
    65  var theTC = newTypeCache()
    66  
    67  type typeCache struct {
    68  	cur atomic.Value
    69  
    70  	// This lock synchronizes writers.
    71  	mu   sync.Mutex
    72  	next map[typekey]*typeinfo
    73  }
    74  
    75  func newTypeCache() *typeCache {
    76  	c := new(typeCache)
    77  	c.cur.Store(make(map[typekey]*typeinfo))
    78  	return c
    79  }
    80  
    81  func cachedDecoder(typ reflect.Type) (decoder, error) {
    82  	info := theTC.info(typ)
    83  	return info.decoder, info.decoderErr
    84  }
    85  
    86  func cachedWriter(typ reflect.Type) (writer, error) {
    87  	info := theTC.info(typ)
    88  	return info.writer, info.writerErr
    89  }
    90  
    91  func (c *typeCache) info(typ reflect.Type) *typeinfo {
    92  	key := typekey{Type: typ}
    93  	if info := c.cur.Load().(map[typekey]*typeinfo)[key]; info != nil {
    94  		return info
    95  	}
    96  
    97  	// Not in the cache, need to generate info for this type.
    98  	return c.generate(typ, tags{})
    99  }
   100  
   101  func (c *typeCache) generate(typ reflect.Type, tags tags) *typeinfo {
   102  	c.mu.Lock()
   103  	defer c.mu.Unlock()
   104  
   105  	cur := c.cur.Load().(map[typekey]*typeinfo)
   106  	if info := cur[typekey{typ, tags}]; info != nil {
   107  		return info
   108  	}
   109  
   110  	// Copy cur to next.
   111  	c.next = make(map[typekey]*typeinfo, len(cur)+1)
   112  	for k, v := range cur {
   113  		c.next[k] = v
   114  	}
   115  
   116  	// Generate.
   117  	info := c.infoWhileGenerating(typ, tags)
   118  
   119  	// next -> cur
   120  	c.cur.Store(c.next)
   121  	c.next = nil
   122  	return info
   123  }
   124  
   125  func (c *typeCache) infoWhileGenerating(typ reflect.Type, tags tags) *typeinfo {
   126  	key := typekey{typ, tags}
   127  	if info := c.next[key]; info != nil {
   128  		return info
   129  	}
   130  	// Put a dummy value into the cache before generating.
   131  	// If the generator tries to lookup itself, it will get
   132  	// the dummy value and won't call itself recursively.
   133  	info := new(typeinfo)
   134  	c.next[key] = info
   135  	info.generate(typ, tags)
   136  	return info
   137  }
   138  
   139  type field struct {
   140  	index    int
   141  	info     *typeinfo
   142  	optional bool
   143  }
   144  
   145  // structFields resolves the typeinfo of all public fields in a struct type.
   146  func structFields(typ reflect.Type) (fields []field, err error) {
   147  	var (
   148  		lastPublic  = lastPublicField(typ)
   149  		anyOptional = false
   150  	)
   151  	for i := 0; i < typ.NumField(); i++ {
   152  		if f := typ.Field(i); f.PkgPath == "" { // exported
   153  			tags, err := parseStructTag(typ, i, lastPublic)
   154  			if err != nil {
   155  				return nil, err
   156  			}
   157  
   158  			// Skip rlp:"-" fields.
   159  			if tags.ignored {
   160  				continue
   161  			}
   162  			// If any field has the "optional" tag, subsequent fields must also have it.
   163  			if tags.optional || tags.tail {
   164  				anyOptional = true
   165  			} else if anyOptional {
   166  				return nil, fmt.Errorf(`rlp: struct field %v.%s needs "optional" tag`, typ, f.Name)
   167  			}
   168  			info := theTC.infoWhileGenerating(f.Type, tags)
   169  			fields = append(fields, field{i, info, tags.optional})
   170  		}
   171  	}
   172  	return fields, nil
   173  }
   174  
   175  type structFieldError struct {
   176  	typ   reflect.Type
   177  	field int
   178  	err   error
   179  }
   180  
   181  func (e structFieldError) Error() string {
   182  	return fmt.Sprintf("%v (struct field %v.%s)", e.err, e.typ, e.typ.Field(e.field).Name)
   183  }
   184  
   185  type structTagError struct {
   186  	typ             reflect.Type
   187  	field, tag, err string
   188  }
   189  
   190  func (e structTagError) Error() string {
   191  	return fmt.Sprintf("rlp: invalid struct tag %q for %v.%s (%s)", e.tag, e.typ, e.field, e.err)
   192  }
   193  
   194  func parseStructTag(typ reflect.Type, fi, lastPublic int) (tags, error) {
   195  	f := typ.Field(fi)
   196  	var ts tags
   197  	for _, t := range strings.Split(f.Tag.Get("rlp"), ",") {
   198  		switch t = strings.TrimSpace(t); t {
   199  		case "":
   200  		case "-":
   201  			ts.ignored = true
   202  		case "nil", "nilString", "nilList":
   203  			ts.nilOK = true
   204  			if f.Type.Kind() != reflect.Ptr {
   205  				return ts, structTagError{typ, f.Name, t, "field is not a pointer"}
   206  			}
   207  			switch t {
   208  			case "nil":
   209  				ts.nilKind = defaultNilKind(f.Type.Elem())
   210  			case "nilString":
   211  				ts.nilKind = String
   212  			case "nilList":
   213  				ts.nilKind = List
   214  			}
   215  		case "optional":
   216  			ts.optional = true
   217  			if ts.tail {
   218  				return ts, structTagError{typ, f.Name, t, `also has "tail" tag`}
   219  			}
   220  		case "tail":
   221  			ts.tail = true
   222  			if fi != lastPublic {
   223  				return ts, structTagError{typ, f.Name, t, "must be on last field"}
   224  			}
   225  			if ts.optional {
   226  				return ts, structTagError{typ, f.Name, t, `also has "optional" tag`}
   227  			}
   228  			if f.Type.Kind() != reflect.Slice {
   229  				return ts, structTagError{typ, f.Name, t, "field type is not slice"}
   230  			}
   231  		default:
   232  			return ts, fmt.Errorf("rlp: unknown struct tag %q on %v.%s", t, typ, f.Name)
   233  		}
   234  	}
   235  	return ts, nil
   236  }
   237  
   238  func lastPublicField(typ reflect.Type) int {
   239  	last := 0
   240  	for i := 0; i < typ.NumField(); i++ {
   241  		if typ.Field(i).PkgPath == "" {
   242  			last = i
   243  		}
   244  	}
   245  	return last
   246  }
   247  
   248  func (i *typeinfo) generate(typ reflect.Type, tags tags) {
   249  	i.decoder, i.decoderErr = makeDecoder(typ, tags)
   250  	i.writer, i.writerErr = makeWriter(typ, tags)
   251  }
   252  
   253  // defaultNilKind determines whether a nil pointer to typ encodes/decodes
   254  // as an empty string or empty list.
   255  func defaultNilKind(typ reflect.Type) Kind {
   256  	k := typ.Kind()
   257  	if isUint(k) || k == reflect.String || k == reflect.Bool || isByteArray(typ) {
   258  		return String
   259  	}
   260  	return List
   261  }
   262  
   263  func isUint(k reflect.Kind) bool {
   264  	return k >= reflect.Uint && k <= reflect.Uintptr
   265  }
   266  
   267  func isByte(typ reflect.Type) bool {
   268  	return typ.Kind() == reflect.Uint8 && !typ.Implements(encoderInterface)
   269  }
   270  
   271  func isByteArray(typ reflect.Type) bool {
   272  	return (typ.Kind() == reflect.Slice || typ.Kind() == reflect.Array) && isByte(typ.Elem())
   273  }