github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/rlp/typecache.go (about) 1 2 //此源码被清华学神尹成大魔王专业翻译分析并修改 3 //尹成QQ77025077 4 //尹成微信18510341407 5 //尹成所在QQ群721929980 6 //尹成邮箱 yinc13@mails.tsinghua.edu.cn 7 //尹成毕业于清华大学,微软区块链领域全球最有价值专家 8 //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620 9 //版权所有2014 Go Ethereum作者 10 //此文件是Go以太坊库的一部分。 11 // 12 //Go-Ethereum库是免费软件:您可以重新分发它和/或修改 13 //根据GNU发布的较低通用公共许可证的条款 14 //自由软件基金会,或者许可证的第3版,或者 15 //(由您选择)任何更高版本。 16 // 17 //Go以太坊图书馆的发行目的是希望它会有用, 18 //但没有任何保证;甚至没有 19 //适销性或特定用途的适用性。见 20 //GNU较低的通用公共许可证,了解更多详细信息。 21 // 22 //你应该收到一份GNU较低级别的公共许可证副本 23 //以及Go以太坊图书馆。如果没有,请参见<http://www.gnu.org/licenses/>。 24 25 package rlp 26 27 import ( 28 "fmt" 29 "reflect" 30 "strings" 31 "sync" 32 ) 33 34 var ( 35 typeCacheMutex sync.RWMutex 36 typeCache = make(map[typekey]*typeinfo) 37 ) 38 39 type typeinfo struct { 40 decoder 41 writer 42 } 43 44 //表示结构标记 45 type tags struct { 46 //rlp:“nil”控制空输入是否导致nil指针。 47 nilOK bool 48 //rlp:“tail”控制此字段是否吞咽附加列表 49 //元素。只能为最后一个字段设置,必须 50 //薄片型。 51 tail bool 52 //RLP:“-”忽略字段。 53 ignored bool 54 } 55 56 type typekey struct { 57 reflect.Type 58 //键必须包含结构标记,因为它们 59 //可能会生成不同的解码器。 60 tags 61 } 62 63 type decoder func(*Stream, reflect.Value) error 64 65 type writer func(reflect.Value, *encbuf) error 66 67 func cachedTypeInfo(typ reflect.Type, tags tags) (*typeinfo, error) { 68 typeCacheMutex.RLock() 69 info := typeCache[typekey{typ, tags}] 70 typeCacheMutex.RUnlock() 71 if info != nil { 72 return info, nil 73 } 74 //不在缓存中,需要为此类型生成信息。 75 typeCacheMutex.Lock() 76 defer typeCacheMutex.Unlock() 77 return cachedTypeInfo1(typ, tags) 78 } 79 80 func cachedTypeInfo1(typ reflect.Type, tags tags) (*typeinfo, error) { 81 key := typekey{typ, tags} 82 info := typeCache[key] 83 if info != nil { 84 //另一个goroutine先得到了写锁 85 return info, nil 86 } 87 //在生成之前将一个dummy值放入缓存。 88 //如果生成器试图查找自身,它将 89 //虚拟值,不会递归调用自己。 90 typeCache[key] = new(typeinfo) 91 info, err := genTypeInfo(typ, tags) 92 if err != nil { 93 //如果发电机发生故障,移除虚拟值 94 delete(typeCache, key) 95 return nil, err 96 } 97 *typeCache[key] = *info 98 return typeCache[key], err 99 } 100 101 type field struct { 102 index int 103 info *typeinfo 104 } 105 106 func structFields(typ reflect.Type) (fields []field, err error) { 107 for i := 0; i < typ.NumField(); i++ { 108 if f := typ.Field(i); f.PkgPath == "" { //出口 109 tags, err := parseStructTag(typ, i) 110 if err != nil { 111 return nil, err 112 } 113 if tags.ignored { 114 continue 115 } 116 info, err := cachedTypeInfo1(f.Type, tags) 117 if err != nil { 118 return nil, err 119 } 120 fields = append(fields, field{i, info}) 121 } 122 } 123 return fields, nil 124 } 125 126 func parseStructTag(typ reflect.Type, fi int) (tags, error) { 127 f := typ.Field(fi) 128 var ts tags 129 for _, t := range strings.Split(f.Tag.Get("rlp"), ",") { 130 switch t = strings.TrimSpace(t); t { 131 case "": 132 case "-": 133 ts.ignored = true 134 case "nil": 135 ts.nilOK = true 136 case "tail": 137 ts.tail = true 138 if fi != typ.NumField()-1 { 139 return ts, fmt.Errorf(`rlp: invalid struct tag "tail" for %v.%s (must be on last field)`, typ, f.Name) 140 } 141 if f.Type.Kind() != reflect.Slice { 142 return ts, fmt.Errorf(`rlp: invalid struct tag "tail" for %v.%s (field type is not slice)`, typ, f.Name) 143 } 144 default: 145 return ts, fmt.Errorf("rlp: unknown struct tag %q on %v.%s", t, typ, f.Name) 146 } 147 } 148 return ts, nil 149 } 150 151 func genTypeInfo(typ reflect.Type, tags tags) (info *typeinfo, err error) { 152 info = new(typeinfo) 153 if info.decoder, err = makeDecoder(typ, tags); err != nil { 154 return nil, err 155 } 156 if info.writer, err = makeWriter(typ, tags); err != nil { 157 return nil, err 158 } 159 return info, nil 160 } 161 162 func isUint(k reflect.Kind) bool { 163 return k >= reflect.Uint && k <= reflect.Uintptr 164 }