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 }