package gob
import (
"encoding"
"errors"
"internal/saferio"
"io"
"math"
"math/bits"
"reflect"
)
var (
errBadUint = errors .New ("gob: encoded unsigned integer out of range" )
errBadType = errors .New ("gob: unknown type id or corrupted data" )
errRange = errors .New ("gob: bad data: field numbers out of bounds" )
)
type decHelper func (state *decoderState , v reflect .Value , length int , ovfl error ) bool
type decoderState struct {
dec *Decoder
b *decBuffer
fieldnum int
next *decoderState
}
type decBuffer struct {
data []byte
offset int
}
func (d *decBuffer ) Read (p []byte ) (int , error ) {
n := copy (p , d .data [d .offset :])
if n == 0 && len (p ) != 0 {
return 0 , io .EOF
}
d .offset += n
return n , nil
}
func (d *decBuffer ) Drop (n int ) {
if n > d .Len () {
panic ("drop" )
}
d .offset += n
}
func (d *decBuffer ) ReadByte () (byte , error ) {
if d .offset >= len (d .data ) {
return 0 , io .EOF
}
c := d .data [d .offset ]
d .offset ++
return c , nil
}
func (d *decBuffer ) Len () int {
return len (d .data ) - d .offset
}
func (d *decBuffer ) Bytes () []byte {
return d .data [d .offset :]
}
func (d *decBuffer ) SetBytes (data []byte ) {
d .data = data
d .offset = 0
}
func (d *decBuffer ) Reset () {
d .data = d .data [0 :0 ]
d .offset = 0
}
func (dec *Decoder ) newDecoderState (buf *decBuffer ) *decoderState {
d := dec .freeList
if d == nil {
d = new (decoderState )
d .dec = dec
} else {
dec .freeList = d .next
}
d .b = buf
return d
}
func (dec *Decoder ) freeDecoderState (d *decoderState ) {
d .next = dec .freeList
dec .freeList = d
}
func overflow(name string ) error {
return errors .New (`value for "` + name + `" out of range` )
}
func decodeUintReader(r io .Reader , buf []byte ) (x uint64 , width int , err error ) {
width = 1
n , err := io .ReadFull (r , buf [0 :width ])
if n == 0 {
return
}
b := buf [0 ]
if b <= 0x7f {
return uint64 (b ), width , nil
}
n = -int (int8 (b ))
if n > uint64Size {
err = errBadUint
return
}
width , err = io .ReadFull (r , buf [0 :n ])
if err != nil {
if err == io .EOF {
err = io .ErrUnexpectedEOF
}
return
}
for _ , b := range buf [0 :width ] {
x = x <<8 | uint64 (b )
}
width ++
return
}
func (state *decoderState ) decodeUint () (x uint64 ) {
b , err := state .b .ReadByte ()
if err != nil {
error_ (err )
}
if b <= 0x7f {
return uint64 (b )
}
n := -int (int8 (b ))
if n > uint64Size {
error_ (errBadUint )
}
buf := state .b .Bytes ()
if len (buf ) < n {
errorf ("invalid uint data length %d: exceeds input size %d" , n , len (buf ))
}
for _ , b := range buf [0 :n ] {
x = x <<8 | uint64 (b )
}
state .b .Drop (n )
return x
}
func (state *decoderState ) decodeInt () int64 {
x := state .decodeUint ()
if x &1 != 0 {
return ^int64 (x >> 1 )
}
return int64 (x >> 1 )
}
func (state *decoderState ) getLength () (int , bool ) {
n := int (state .decodeUint ())
if n < 0 || state .b .Len () < n || tooBig <= n {
return 0 , false
}
return n , true
}
type decOp func (i *decInstr , state *decoderState , v reflect .Value )
type decInstr struct {
op decOp
field int
index []int
ovfl error
}
func ignoreUint(i *decInstr , state *decoderState , v reflect .Value ) {
state .decodeUint ()
}
func ignoreTwoUints(i *decInstr , state *decoderState , v reflect .Value ) {
state .decodeUint ()
state .decodeUint ()
}
func decAlloc(v reflect .Value ) reflect .Value {
for v .Kind () == reflect .Pointer {
if v .IsNil () {
v .Set (reflect .New (v .Type ().Elem ()))
}
v = v .Elem ()
}
return v
}
func decBool(i *decInstr , state *decoderState , value reflect .Value ) {
value .SetBool (state .decodeUint () != 0 )
}
func decInt8(i *decInstr , state *decoderState , value reflect .Value ) {
v := state .decodeInt ()
if v < math .MinInt8 || math .MaxInt8 < v {
error_ (i .ovfl )
}
value .SetInt (v )
}
func decUint8(i *decInstr , state *decoderState , value reflect .Value ) {
v := state .decodeUint ()
if math .MaxUint8 < v {
error_ (i .ovfl )
}
value .SetUint (v )
}
func decInt16(i *decInstr , state *decoderState , value reflect .Value ) {
v := state .decodeInt ()
if v < math .MinInt16 || math .MaxInt16 < v {
error_ (i .ovfl )
}
value .SetInt (v )
}
func decUint16(i *decInstr , state *decoderState , value reflect .Value ) {
v := state .decodeUint ()
if math .MaxUint16 < v {
error_ (i .ovfl )
}
value .SetUint (v )
}
func decInt32(i *decInstr , state *decoderState , value reflect .Value ) {
v := state .decodeInt ()
if v < math .MinInt32 || math .MaxInt32 < v {
error_ (i .ovfl )
}
value .SetInt (v )
}
func decUint32(i *decInstr , state *decoderState , value reflect .Value ) {
v := state .decodeUint ()
if math .MaxUint32 < v {
error_ (i .ovfl )
}
value .SetUint (v )
}
func decInt64(i *decInstr , state *decoderState , value reflect .Value ) {
v := state .decodeInt ()
value .SetInt (v )
}
func decUint64(i *decInstr , state *decoderState , value reflect .Value ) {
v := state .decodeUint ()
value .SetUint (v )
}
func float64FromBits(u uint64 ) float64 {
v := bits .ReverseBytes64 (u )
return math .Float64frombits (v )
}
func float32FromBits(u uint64 , ovfl error ) float64 {
v := float64FromBits (u )
av := v
if av < 0 {
av = -av
}
if math .MaxFloat32 < av && av <= math .MaxFloat64 {
error_ (ovfl )
}
return v
}
func decFloat32(i *decInstr , state *decoderState , value reflect .Value ) {
value .SetFloat (float32FromBits (state .decodeUint (), i .ovfl ))
}
func decFloat64(i *decInstr , state *decoderState , value reflect .Value ) {
value .SetFloat (float64FromBits (state .decodeUint ()))
}
func decComplex64(i *decInstr , state *decoderState , value reflect .Value ) {
real := float32FromBits (state .decodeUint (), i .ovfl )
imag := float32FromBits (state .decodeUint (), i .ovfl )
value .SetComplex (complex (real , imag ))
}
func decComplex128(i *decInstr , state *decoderState , value reflect .Value ) {
real := float64FromBits (state .decodeUint ())
imag := float64FromBits (state .decodeUint ())
value .SetComplex (complex (real , imag ))
}
func decUint8Slice(i *decInstr , state *decoderState , value reflect .Value ) {
n , ok := state .getLength ()
if !ok {
errorf ("bad %s slice length: %d" , value .Type (), n )
}
if value .Cap () < n {
safe := saferio .SliceCap [byte ](uint64 (n ))
if safe < 0 {
errorf ("%s slice too big: %d elements" , value .Type (), n )
}
value .Set (reflect .MakeSlice (value .Type (), safe , safe ))
ln := safe
i := 0
for i < n {
if i >= ln {
value .Grow (1 )
}
ln = value .Cap ()
if ln > n {
ln = n
}
value .SetLen (ln )
sub := value .Slice (i , ln )
if _ , err := state .b .Read (sub .Bytes ()); err != nil {
errorf ("error decoding []byte at %d: %s" , i , err )
}
i = ln
}
} else {
value .SetLen (n )
if _ , err := state .b .Read (value .Bytes ()); err != nil {
errorf ("error decoding []byte: %s" , err )
}
}
}
func decString(i *decInstr , state *decoderState , value reflect .Value ) {
n , ok := state .getLength ()
if !ok {
errorf ("bad %s slice length: %d" , value .Type (), n )
}
data := state .b .Bytes ()
if len (data ) < n {
errorf ("invalid string length %d: exceeds input size %d" , n , len (data ))
}
s := string (data [:n ])
state .b .Drop (n )
value .SetString (s )
}
func ignoreUint8Array(i *decInstr , state *decoderState , value reflect .Value ) {
n , ok := state .getLength ()
if !ok {
errorf ("slice length too large" )
}
bn := state .b .Len ()
if bn < n {
errorf ("invalid slice length %d: exceeds input size %d" , n , bn )
}
state .b .Drop (n )
}
type decEngine struct {
instr []decInstr
numInstr int
}
func (dec *Decoder ) decodeSingle (engine *decEngine , value reflect .Value ) {
state := dec .newDecoderState (&dec .buf )
defer dec .freeDecoderState (state )
state .fieldnum = singletonField
if state .decodeUint () != 0 {
errorf ("decode: corrupted data: non-zero delta for singleton" )
}
instr := &engine .instr [singletonField ]
instr .op (instr , state , value )
}
func (dec *Decoder ) decodeStruct (engine *decEngine , value reflect .Value ) {
state := dec .newDecoderState (&dec .buf )
defer dec .freeDecoderState (state )
state .fieldnum = -1
for state .b .Len () > 0 {
delta := int (state .decodeUint ())
if delta < 0 {
errorf ("decode: corrupted data: negative delta" )
}
if delta == 0 {
break
}
if state .fieldnum >= len (engine .instr )-delta {
error_ (errRange )
}
fieldnum := state .fieldnum + delta
instr := &engine .instr [fieldnum ]
var field reflect .Value
if instr .index != nil {
field = value .FieldByIndex (instr .index )
if field .Kind () == reflect .Pointer {
field = decAlloc (field )
}
}
instr .op (instr , state , field )
state .fieldnum = fieldnum
}
}
var noValue reflect .Value
func (dec *Decoder ) ignoreStruct (engine *decEngine ) {
state := dec .newDecoderState (&dec .buf )
defer dec .freeDecoderState (state )
state .fieldnum = -1
for state .b .Len () > 0 {
delta := int (state .decodeUint ())
if delta < 0 {
errorf ("ignore decode: corrupted data: negative delta" )
}
if delta == 0 {
break
}
fieldnum := state .fieldnum + delta
if fieldnum >= len (engine .instr ) {
error_ (errRange )
}
instr := &engine .instr [fieldnum ]
instr .op (instr , state , noValue )
state .fieldnum = fieldnum
}
}
func (dec *Decoder ) ignoreSingle (engine *decEngine ) {
state := dec .newDecoderState (&dec .buf )
defer dec .freeDecoderState (state )
state .fieldnum = singletonField
delta := int (state .decodeUint ())
if delta != 0 {
errorf ("decode: corrupted data: non-zero delta for singleton" )
}
instr := &engine .instr [singletonField ]
instr .op (instr , state , noValue )
}
func (dec *Decoder ) decodeArrayHelper (state *decoderState , value reflect .Value , elemOp decOp , length int , ovfl error , helper decHelper ) {
if helper != nil && helper (state , value , length , ovfl ) {
return
}
instr := &decInstr {elemOp , 0 , nil , ovfl }
isPtr := value .Type ().Elem ().Kind () == reflect .Pointer
ln := value .Len ()
for i := 0 ; i < length ; i ++ {
if state .b .Len () == 0 {
errorf ("decoding array or slice: length exceeds input size (%d elements)" , length )
}
if i >= ln {
value .Grow (1 )
cp := value .Cap ()
if cp > length {
cp = length
}
value .SetLen (cp )
ln = cp
}
v := value .Index (i )
if isPtr {
v = decAlloc (v )
}
elemOp (instr , state , v )
}
}
func (dec *Decoder ) decodeArray (state *decoderState , value reflect .Value , elemOp decOp , length int , ovfl error , helper decHelper ) {
if n := state .decodeUint (); n != uint64 (length ) {
errorf ("length mismatch in decodeArray" )
}
dec .decodeArrayHelper (state , value , elemOp , length , ovfl , helper )
}
func decodeIntoValue(state *decoderState , op decOp , isPtr bool , value reflect .Value , instr *decInstr ) reflect .Value {
v := value
if isPtr {
v = decAlloc (value )
}
op (instr , state , v )
return value
}
func (dec *Decoder ) decodeMap (mtyp reflect .Type , state *decoderState , value reflect .Value , keyOp , elemOp decOp , ovfl error ) {
n := int (state .decodeUint ())
if value .IsNil () {
value .Set (reflect .MakeMapWithSize (mtyp , n ))
}
keyIsPtr := mtyp .Key ().Kind () == reflect .Pointer
elemIsPtr := mtyp .Elem ().Kind () == reflect .Pointer
keyInstr := &decInstr {keyOp , 0 , nil , ovfl }
elemInstr := &decInstr {elemOp , 0 , nil , ovfl }
keyP := reflect .New (mtyp .Key ())
elemP := reflect .New (mtyp .Elem ())
for i := 0 ; i < n ; i ++ {
key := decodeIntoValue (state , keyOp , keyIsPtr , keyP .Elem (), keyInstr )
elem := decodeIntoValue (state , elemOp , elemIsPtr , elemP .Elem (), elemInstr )
value .SetMapIndex (key , elem )
keyP .Elem ().SetZero ()
elemP .Elem ().SetZero ()
}
}
func (dec *Decoder ) ignoreArrayHelper (state *decoderState , elemOp decOp , length int ) {
instr := &decInstr {elemOp , 0 , nil , errors .New ("no error" )}
for i := 0 ; i < length ; i ++ {
if state .b .Len () == 0 {
errorf ("decoding array or slice: length exceeds input size (%d elements)" , length )
}
elemOp (instr , state , noValue )
}
}
func (dec *Decoder ) ignoreArray (state *decoderState , elemOp decOp , length int ) {
if n := state .decodeUint (); n != uint64 (length ) {
errorf ("length mismatch in ignoreArray" )
}
dec .ignoreArrayHelper (state , elemOp , length )
}
func (dec *Decoder ) ignoreMap (state *decoderState , keyOp , elemOp decOp ) {
n := int (state .decodeUint ())
keyInstr := &decInstr {keyOp , 0 , nil , errors .New ("no error" )}
elemInstr := &decInstr {elemOp , 0 , nil , errors .New ("no error" )}
for i := 0 ; i < n ; i ++ {
keyOp (keyInstr , state , noValue )
elemOp (elemInstr , state , noValue )
}
}
func (dec *Decoder ) decodeSlice (state *decoderState , value reflect .Value , elemOp decOp , ovfl error , helper decHelper ) {
u := state .decodeUint ()
typ := value .Type ()
size := uint64 (typ .Elem ().Size ())
nBytes := u * size
n := int (u )
if n < 0 || uint64 (n ) != u || nBytes > tooBig || (size > 0 && nBytes /size != u ) {
errorf ("%s slice too big: %d elements of %d bytes" , typ .Elem (), u , size )
}
if value .Cap () < n {
safe := saferio .SliceCapWithSize (size , uint64 (n ))
if safe < 0 {
errorf ("%s slice too big: %d elements of %d bytes" , typ .Elem (), u , size )
}
value .Set (reflect .MakeSlice (typ , safe , safe ))
} else {
value .SetLen (n )
}
dec .decodeArrayHelper (state , value , elemOp , n , ovfl , helper )
}
func (dec *Decoder ) ignoreSlice (state *decoderState , elemOp decOp ) {
dec .ignoreArrayHelper (state , elemOp , int (state .decodeUint ()))
}
func (dec *Decoder ) decodeInterface (ityp reflect .Type , state *decoderState , value reflect .Value ) {
nr := state .decodeUint ()
if nr > 1 <<31 {
errorf ("invalid type name length %d" , nr )
}
if nr > uint64 (state .b .Len ()) {
errorf ("invalid type name length %d: exceeds input size" , nr )
}
n := int (nr )
name := state .b .Bytes ()[:n ]
state .b .Drop (n )
if len (name ) == 0 {
value .SetZero ()
return
}
if len (name ) > 1024 {
errorf ("name too long (%d bytes): %.20q..." , len (name ), name )
}
typi , ok := nameToConcreteType .Load (string (name ))
if !ok {
errorf ("name not registered for interface: %q" , name )
}
typ := typi .(reflect .Type )
concreteId := dec .decodeTypeSequence (true )
if concreteId < 0 {
error_ (dec .err )
}
state .decodeUint ()
v := allocValue (typ )
dec .decodeValue (concreteId , v )
if dec .err != nil {
error_ (dec .err )
}
if !typ .AssignableTo (ityp ) {
errorf ("%s is not assignable to type %s" , typ , ityp )
}
value .Set (v )
}
func (dec *Decoder ) ignoreInterface (state *decoderState ) {
n , ok := state .getLength ()
if !ok {
errorf ("bad interface encoding: name too large for buffer" )
}
bn := state .b .Len ()
if bn < n {
errorf ("invalid interface value length %d: exceeds input size %d" , n , bn )
}
state .b .Drop (n )
id := dec .decodeTypeSequence (true )
if id < 0 {
error_ (dec .err )
}
n , ok = state .getLength ()
if !ok {
errorf ("bad interface encoding: data length too large for buffer" )
}
state .b .Drop (n )
}
func (dec *Decoder ) decodeGobDecoder (ut *userTypeInfo , state *decoderState , value reflect .Value ) {
n , ok := state .getLength ()
if !ok {
errorf ("GobDecoder: length too large for buffer" )
}
b := state .b .Bytes ()
if len (b ) < n {
errorf ("GobDecoder: invalid data length %d: exceeds input size %d" , n , len (b ))
}
b = b [:n ]
state .b .Drop (n )
var err error
switch ut .externalDec {
case xGob :
err = value .Interface ().(GobDecoder ).GobDecode (b )
case xBinary :
err = value .Interface ().(encoding .BinaryUnmarshaler ).UnmarshalBinary (b )
case xText :
err = value .Interface ().(encoding .TextUnmarshaler ).UnmarshalText (b )
}
if err != nil {
error_ (err )
}
}
func (dec *Decoder ) ignoreGobDecoder (state *decoderState ) {
n , ok := state .getLength ()
if !ok {
errorf ("GobDecoder: length too large for buffer" )
}
bn := state .b .Len ()
if bn < n {
errorf ("GobDecoder: invalid data length %d: exceeds input size %d" , n , bn )
}
state .b .Drop (n )
}
var decOpTable = [...]decOp {
reflect .Bool : decBool ,
reflect .Int8 : decInt8 ,
reflect .Int16 : decInt16 ,
reflect .Int32 : decInt32 ,
reflect .Int64 : decInt64 ,
reflect .Uint8 : decUint8 ,
reflect .Uint16 : decUint16 ,
reflect .Uint32 : decUint32 ,
reflect .Uint64 : decUint64 ,
reflect .Float32 : decFloat32 ,
reflect .Float64 : decFloat64 ,
reflect .Complex64 : decComplex64 ,
reflect .Complex128 : decComplex128 ,
reflect .String : decString ,
}
var decIgnoreOpMap = map [typeId ]decOp {
tBool : ignoreUint ,
tInt : ignoreUint ,
tUint : ignoreUint ,
tFloat : ignoreUint ,
tBytes : ignoreUint8Array ,
tString : ignoreUint8Array ,
tComplex : ignoreTwoUints ,
}
func (dec *Decoder ) decOpFor (wireId typeId , rt reflect .Type , name string , inProgress map [reflect .Type ]*decOp ) *decOp {
ut := userType (rt )
if ut .externalDec != 0 {
return dec .gobDecodeOpFor (ut )
}
if opPtr := inProgress [rt ]; opPtr != nil {
return opPtr
}
typ := ut .base
var op decOp
k := typ .Kind ()
if int (k ) < len (decOpTable ) {
op = decOpTable [k ]
}
if op == nil {
inProgress [rt ] = &op
switch t := typ ; t .Kind () {
case reflect .Array :
name = "element of " + name
elemId := dec .wireType [wireId ].ArrayT .Elem
elemOp := dec .decOpFor (elemId , t .Elem (), name , inProgress )
ovfl := overflow (name )
helper := decArrayHelper [t .Elem ().Kind ()]
op = func (i *decInstr , state *decoderState , value reflect .Value ) {
state .dec .decodeArray (state , value , *elemOp , t .Len (), ovfl , helper )
}
case reflect .Map :
keyId := dec .wireType [wireId ].MapT .Key
elemId := dec .wireType [wireId ].MapT .Elem
keyOp := dec .decOpFor (keyId , t .Key (), "key of " +name , inProgress )
elemOp := dec .decOpFor (elemId , t .Elem (), "element of " +name , inProgress )
ovfl := overflow (name )
op = func (i *decInstr , state *decoderState , value reflect .Value ) {
state .dec .decodeMap (t , state , value , *keyOp , *elemOp , ovfl )
}
case reflect .Slice :
name = "element of " + name
if t .Elem ().Kind () == reflect .Uint8 {
op = decUint8Slice
break
}
var elemId typeId
if tt := builtinIdToType (wireId ); tt != nil {
elemId = tt .(*sliceType ).Elem
} else {
elemId = dec .wireType [wireId ].SliceT .Elem
}
elemOp := dec .decOpFor (elemId , t .Elem (), name , inProgress )
ovfl := overflow (name )
helper := decSliceHelper [t .Elem ().Kind ()]
op = func (i *decInstr , state *decoderState , value reflect .Value ) {
state .dec .decodeSlice (state , value , *elemOp , ovfl , helper )
}
case reflect .Struct :
ut := userType (typ )
enginePtr , err := dec .getDecEnginePtr (wireId , ut )
if err != nil {
error_ (err )
}
op = func (i *decInstr , state *decoderState , value reflect .Value ) {
dec .decodeStruct (*enginePtr , value )
}
case reflect .Interface :
op = func (i *decInstr , state *decoderState , value reflect .Value ) {
state .dec .decodeInterface (t , state , value )
}
}
}
if op == nil {
errorf ("decode can't handle type %s" , rt )
}
return &op
}
var maxIgnoreNestingDepth = 10000
func (dec *Decoder ) decIgnoreOpFor (wireId typeId , inProgress map [typeId ]*decOp , depth int ) *decOp {
if depth > maxIgnoreNestingDepth {
error_ (errors .New ("invalid nesting depth" ))
}
if opPtr := inProgress [wireId ]; opPtr != nil {
return opPtr
}
op , ok := decIgnoreOpMap [wireId ]
if !ok {
inProgress [wireId ] = &op
if wireId == tInterface {
op = func (i *decInstr , state *decoderState , value reflect .Value ) {
state .dec .ignoreInterface (state )
}
return &op
}
wire := dec .wireType [wireId ]
switch {
case wire == nil :
errorf ("bad data: undefined type %s" , wireId .string ())
case wire .ArrayT != nil :
elemId := wire .ArrayT .Elem
elemOp := dec .decIgnoreOpFor (elemId , inProgress , depth +1 )
op = func (i *decInstr , state *decoderState , value reflect .Value ) {
state .dec .ignoreArray (state , *elemOp , wire .ArrayT .Len )
}
case wire .MapT != nil :
keyId := dec .wireType [wireId ].MapT .Key
elemId := dec .wireType [wireId ].MapT .Elem
keyOp := dec .decIgnoreOpFor (keyId , inProgress , depth +1 )
elemOp := dec .decIgnoreOpFor (elemId , inProgress , depth +1 )
op = func (i *decInstr , state *decoderState , value reflect .Value ) {
state .dec .ignoreMap (state , *keyOp , *elemOp )
}
case wire .SliceT != nil :
elemId := wire .SliceT .Elem
elemOp := dec .decIgnoreOpFor (elemId , inProgress , depth +1 )
op = func (i *decInstr , state *decoderState , value reflect .Value ) {
state .dec .ignoreSlice (state , *elemOp )
}
case wire .StructT != nil :
enginePtr , err := dec .getIgnoreEnginePtr (wireId )
if err != nil {
error_ (err )
}
op = func (i *decInstr , state *decoderState , value reflect .Value ) {
state .dec .ignoreStruct (*enginePtr )
}
case wire .GobEncoderT != nil , wire .BinaryMarshalerT != nil , wire .TextMarshalerT != nil :
op = func (i *decInstr , state *decoderState , value reflect .Value ) {
state .dec .ignoreGobDecoder (state )
}
}
}
if op == nil {
errorf ("bad data: ignore can't handle type %s" , wireId .string ())
}
return &op
}
func (dec *Decoder ) gobDecodeOpFor (ut *userTypeInfo ) *decOp {
rcvrType := ut .user
if ut .decIndir == -1 {
rcvrType = reflect .PointerTo (rcvrType )
} else if ut .decIndir > 0 {
for i := int8 (0 ); i < ut .decIndir ; i ++ {
rcvrType = rcvrType .Elem ()
}
}
var op decOp
op = func (i *decInstr , state *decoderState , value reflect .Value ) {
if value .Kind () != reflect .Pointer && rcvrType .Kind () == reflect .Pointer {
value = value .Addr ()
}
state .dec .decodeGobDecoder (ut , state , value )
}
return &op
}
func (dec *Decoder ) compatibleType (fr reflect .Type , fw typeId , inProgress map [reflect .Type ]typeId ) bool {
if rhs , ok := inProgress [fr ]; ok {
return rhs == fw
}
inProgress [fr ] = fw
ut := userType (fr )
wire , ok := dec .wireType [fw ]
if (ut .externalDec == xGob ) != (ok && wire .GobEncoderT != nil ) ||
(ut .externalDec == xBinary ) != (ok && wire .BinaryMarshalerT != nil ) ||
(ut .externalDec == xText ) != (ok && wire .TextMarshalerT != nil ) {
return false
}
if ut .externalDec != 0 {
return true
}
switch t := ut .base ; t .Kind () {
default :
return false
case reflect .Bool :
return fw == tBool
case reflect .Int , reflect .Int8 , reflect .Int16 , reflect .Int32 , reflect .Int64 :
return fw == tInt
case reflect .Uint , reflect .Uint8 , reflect .Uint16 , reflect .Uint32 , reflect .Uint64 , reflect .Uintptr :
return fw == tUint
case reflect .Float32 , reflect .Float64 :
return fw == tFloat
case reflect .Complex64 , reflect .Complex128 :
return fw == tComplex
case reflect .String :
return fw == tString
case reflect .Interface :
return fw == tInterface
case reflect .Array :
if !ok || wire .ArrayT == nil {
return false
}
array := wire .ArrayT
return t .Len () == array .Len && dec .compatibleType (t .Elem (), array .Elem , inProgress )
case reflect .Map :
if !ok || wire .MapT == nil {
return false
}
MapType := wire .MapT
return dec .compatibleType (t .Key (), MapType .Key , inProgress ) && dec .compatibleType (t .Elem (), MapType .Elem , inProgress )
case reflect .Slice :
if t .Elem ().Kind () == reflect .Uint8 {
return fw == tBytes
}
var sw *sliceType
if tt := builtinIdToType (fw ); tt != nil {
sw , _ = tt .(*sliceType )
} else if wire != nil {
sw = wire .SliceT
}
elem := userType (t .Elem ()).base
return sw != nil && dec .compatibleType (elem , sw .Elem , inProgress )
case reflect .Struct :
return true
}
}
func (dec *Decoder ) typeString (remoteId typeId ) string {
typeLock .Lock ()
defer typeLock .Unlock ()
if t := idToType (remoteId ); t != nil {
return t .string ()
}
return dec .wireType [remoteId ].string ()
}
func (dec *Decoder ) compileSingle (remoteId typeId , ut *userTypeInfo ) (engine *decEngine , err error ) {
rt := ut .user
engine = new (decEngine )
engine .instr = make ([]decInstr , 1 )
name := rt .String ()
if !dec .compatibleType (rt , remoteId , make (map [reflect .Type ]typeId )) {
remoteType := dec .typeString (remoteId )
if ut .base .Kind () == reflect .Interface && remoteId != tInterface {
return nil , errors .New ("gob: local interface type " + name + " can only be decoded from remote interface type; received concrete type " + remoteType )
}
return nil , errors .New ("gob: decoding into local type " + name + ", received remote type " + remoteType )
}
op := dec .decOpFor (remoteId , rt , name , make (map [reflect .Type ]*decOp ))
ovfl := errors .New (`value for "` + name + `" out of range` )
engine .instr [singletonField ] = decInstr {*op , singletonField , nil , ovfl }
engine .numInstr = 1
return
}
func (dec *Decoder ) compileIgnoreSingle (remoteId typeId ) *decEngine {
engine := new (decEngine )
engine .instr = make ([]decInstr , 1 )
op := dec .decIgnoreOpFor (remoteId , make (map [typeId ]*decOp ), 0 )
ovfl := overflow (dec .typeString (remoteId ))
engine .instr [0 ] = decInstr {*op , 0 , nil , ovfl }
engine .numInstr = 1
return engine
}
func (dec *Decoder ) compileDec (remoteId typeId , ut *userTypeInfo ) (engine *decEngine , err error ) {
defer catchError (&err )
rt := ut .base
srt := rt
if srt .Kind () != reflect .Struct || ut .externalDec != 0 {
return dec .compileSingle (remoteId , ut )
}
var wireStruct *structType
if t := builtinIdToType (remoteId ); t != nil {
wireStruct , _ = t .(*structType )
} else {
wire := dec .wireType [remoteId ]
if wire == nil {
error_ (errBadType )
}
wireStruct = wire .StructT
}
if wireStruct == nil {
errorf ("type mismatch in decoder: want struct type %s; got non-struct" , rt )
}
engine = new (decEngine )
engine .instr = make ([]decInstr , len (wireStruct .Field ))
seen := make (map [reflect .Type ]*decOp )
for fieldnum := 0 ; fieldnum < len (wireStruct .Field ); fieldnum ++ {
wireField := wireStruct .Field [fieldnum ]
if wireField .Name == "" {
errorf ("empty name for remote field of type %s" , wireStruct .Name )
}
ovfl := overflow (wireField .Name )
localField , present := srt .FieldByName (wireField .Name )
if !present || !isExported (wireField .Name ) {
op := dec .decIgnoreOpFor (wireField .Id , make (map [typeId ]*decOp ), 0 )
engine .instr [fieldnum ] = decInstr {*op , fieldnum , nil , ovfl }
continue
}
if !dec .compatibleType (localField .Type , wireField .Id , make (map [reflect .Type ]typeId )) {
errorf ("wrong type (%s) for received field %s.%s" , localField .Type , wireStruct .Name , wireField .Name )
}
op := dec .decOpFor (wireField .Id , localField .Type , localField .Name , seen )
engine .instr [fieldnum ] = decInstr {*op , fieldnum , localField .Index , ovfl }
engine .numInstr ++
}
return
}
func (dec *Decoder ) getDecEnginePtr (remoteId typeId , ut *userTypeInfo ) (enginePtr **decEngine , err error ) {
rt := ut .user
decoderMap , ok := dec .decoderCache [rt ]
if !ok {
decoderMap = make (map [typeId ]**decEngine )
dec .decoderCache [rt ] = decoderMap
}
if enginePtr , ok = decoderMap [remoteId ]; !ok {
enginePtr = new (*decEngine )
decoderMap [remoteId ] = enginePtr
*enginePtr , err = dec .compileDec (remoteId , ut )
if err != nil {
delete (decoderMap , remoteId )
}
}
return
}
type emptyStruct struct {}
var emptyStructType = reflect .TypeFor [emptyStruct ]()
func (dec *Decoder ) getIgnoreEnginePtr (wireId typeId ) (enginePtr **decEngine , err error ) {
var ok bool
if enginePtr , ok = dec .ignorerCache [wireId ]; !ok {
enginePtr = new (*decEngine )
dec .ignorerCache [wireId ] = enginePtr
wire := dec .wireType [wireId ]
if wire != nil && wire .StructT != nil {
*enginePtr , err = dec .compileDec (wireId , userType (emptyStructType ))
} else {
*enginePtr = dec .compileIgnoreSingle (wireId )
}
if err != nil {
delete (dec .ignorerCache , wireId )
}
}
return
}
func (dec *Decoder ) decodeValue (wireId typeId , value reflect .Value ) {
defer catchError (&dec .err )
if !value .IsValid () {
dec .decodeIgnoredValue (wireId )
return
}
ut := userType (value .Type ())
base := ut .base
var enginePtr **decEngine
enginePtr , dec .err = dec .getDecEnginePtr (wireId , ut )
if dec .err != nil {
return
}
value = decAlloc (value )
engine := *enginePtr
if st := base ; st .Kind () == reflect .Struct && ut .externalDec == 0 {
wt := dec .wireType [wireId ]
if engine .numInstr == 0 && st .NumField () > 0 &&
wt != nil && len (wt .StructT .Field ) > 0 {
name := base .Name ()
errorf ("type mismatch: no fields matched compiling decoder for %s" , name )
}
dec .decodeStruct (engine , value )
} else {
dec .decodeSingle (engine , value )
}
}
func (dec *Decoder ) decodeIgnoredValue (wireId typeId ) {
var enginePtr **decEngine
enginePtr , dec .err = dec .getIgnoreEnginePtr (wireId )
if dec .err != nil {
return
}
wire := dec .wireType [wireId ]
if wire != nil && wire .StructT != nil {
dec .ignoreStruct (*enginePtr )
} else {
dec .ignoreSingle (*enginePtr )
}
}
const (
intBits = 32 << (^uint (0 ) >> 63 )
uintptrBits = 32 << (^uintptr (0 ) >> 63 )
)
func init() {
var iop , uop decOp
switch intBits {
case 32 :
iop = decInt32
uop = decUint32
case 64 :
iop = decInt64
uop = decUint64
default :
panic ("gob: unknown size of int/uint" )
}
decOpTable [reflect .Int ] = iop
decOpTable [reflect .Uint ] = uop
switch uintptrBits {
case 32 :
uop = decUint32
case 64 :
uop = decUint64
default :
panic ("gob: unknown size of uintptr" )
}
decOpTable [reflect .Uintptr ] = uop
}
func allocValue(t reflect .Type ) reflect .Value {
return reflect .New (t ).Elem ()
}
The pages are generated with Golds v0.7.0-preview . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .