gitee.com/liu-zhao234568/cntest@v1.0.0/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 // 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 }