github.com/aidoskuneen/adk-node@v0.0.0-20220315131952-2e32567cb7f4/rlp/typecache.go (about)

     1  // Copyright 2021 The adkgo Authors
     2  // This file is part of the adkgo library (adapted for adkgo from go--ethereum v1.10.8).
     3  //
     4  // the adkgo 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 adkgo 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 adkgo 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  // anyOptionalFields returns the index of the first field with "optional" tag.
   176  func firstOptionalField(fields []field) int {
   177  	for i, f := range fields {
   178  		if f.optional {
   179  			return i
   180  		}
   181  	}
   182  	return len(fields)
   183  }
   184  
   185  type structFieldError struct {
   186  	typ   reflect.Type
   187  	field int
   188  	err   error
   189  }
   190  
   191  func (e structFieldError) Error() string {
   192  	return fmt.Sprintf("%v (struct field %v.%s)", e.err, e.typ, e.typ.Field(e.field).Name)
   193  }
   194  
   195  type structTagError struct {
   196  	typ             reflect.Type
   197  	field, tag, err string
   198  }
   199  
   200  func (e structTagError) Error() string {
   201  	return fmt.Sprintf("rlp: invalid struct tag %q for %v.%s (%s)", e.tag, e.typ, e.field, e.err)
   202  }
   203  
   204  func parseStructTag(typ reflect.Type, fi, lastPublic int) (tags, error) {
   205  	f := typ.Field(fi)
   206  	var ts tags
   207  	for _, t := range strings.Split(f.Tag.Get("rlp"), ",") {
   208  		switch t = strings.TrimSpace(t); t {
   209  		case "":
   210  		case "-":
   211  			ts.ignored = true
   212  		case "nil", "nilString", "nilList":
   213  			ts.nilOK = true
   214  			if f.Type.Kind() != reflect.Ptr {
   215  				return ts, structTagError{typ, f.Name, t, "field is not a pointer"}
   216  			}
   217  			switch t {
   218  			case "nil":
   219  				ts.nilKind = defaultNilKind(f.Type.Elem())
   220  			case "nilString":
   221  				ts.nilKind = String
   222  			case "nilList":
   223  				ts.nilKind = List
   224  			}
   225  		case "optional":
   226  			ts.optional = true
   227  			if ts.tail {
   228  				return ts, structTagError{typ, f.Name, t, `also has "tail" tag`}
   229  			}
   230  		case "tail":
   231  			ts.tail = true
   232  			if fi != lastPublic {
   233  				return ts, structTagError{typ, f.Name, t, "must be on last field"}
   234  			}
   235  			if ts.optional {
   236  				return ts, structTagError{typ, f.Name, t, `also has "optional" tag`}
   237  			}
   238  			if f.Type.Kind() != reflect.Slice {
   239  				return ts, structTagError{typ, f.Name, t, "field type is not slice"}
   240  			}
   241  		default:
   242  			return ts, fmt.Errorf("rlp: unknown struct tag %q on %v.%s", t, typ, f.Name)
   243  		}
   244  	}
   245  	return ts, nil
   246  }
   247  
   248  func lastPublicField(typ reflect.Type) int {
   249  	last := 0
   250  	for i := 0; i < typ.NumField(); i++ {
   251  		if typ.Field(i).PkgPath == "" {
   252  			last = i
   253  		}
   254  	}
   255  	return last
   256  }
   257  
   258  func (i *typeinfo) generate(typ reflect.Type, tags tags) {
   259  	i.decoder, i.decoderErr = makeDecoder(typ, tags)
   260  	i.writer, i.writerErr = makeWriter(typ, tags)
   261  }
   262  
   263  // defaultNilKind determines whether a nil pointer to typ encodes/decodes
   264  // as an empty string or empty list.
   265  func defaultNilKind(typ reflect.Type) Kind {
   266  	k := typ.Kind()
   267  	if isUint(k) || k == reflect.String || k == reflect.Bool || isByteArray(typ) {
   268  		return String
   269  	}
   270  	return List
   271  }
   272  
   273  func isUint(k reflect.Kind) bool {
   274  	return k >= reflect.Uint && k <= reflect.Uintptr
   275  }
   276  
   277  func isByte(typ reflect.Type) bool {
   278  	return typ.Kind() == reflect.Uint8 && !typ.Implements(encoderInterface)
   279  }
   280  
   281  func isByteArray(typ reflect.Type) bool {
   282  	return (typ.Kind() == reflect.Slice || typ.Kind() == reflect.Array) && isByte(typ.Elem())
   283  }