Source File
encode.go
Belonging Package
encoding/gob
package gob
import (
)
const uint64Size = 8
type encHelper func(state *encoderState, v reflect.Value) bool
type encoderState struct {
enc *Encoder
b *encBuffer
sendZero bool // encoding an array element or map key/value pair; send zero values
fieldnum int // the last field number written.
buf [1 + uint64Size]byte // buffer used by the encoder; here to avoid allocation.
next *encoderState // for free list
}
type encBuffer struct {
data []byte
scratch [64]byte
}
var encBufferPool = sync.Pool{
New: func() interface{} {
:= new(encBuffer)
.data = .scratch[0:0]
return
},
}
func ( *encBuffer) ( byte) {
.data = append(.data, )
}
func ( *encBuffer) ( []byte) (int, error) {
.data = append(.data, ...)
return len(), nil
}
func ( *encBuffer) ( string) {
.data = append(.data, ...)
}
func ( *encBuffer) () int {
return len(.data)
}
func ( *encBuffer) () []byte {
return .data
}
func ( *encBuffer) () {
if len(.data) >= tooBig {
.data = .scratch[0:0]
} else {
.data = .data[0:0]
}
}
func ( *Encoder) ( *encBuffer) *encoderState {
:= .freeList
if == nil {
= new(encoderState)
.enc =
} else {
.freeList = .next
}
.sendZero = false
.fieldnum = 0
.b =
if len(.data) == 0 {
.data = .scratch[0:0]
}
return
}
func ( *Encoder) ( *encoderState) {
.next = .freeList
.freeList =
}
func ( *encoderState) ( uint64) {
if <= 0x7F {
.b.writeByte(uint8())
return
}
binary.BigEndian.PutUint64(.buf[1:], )
:= bits.LeadingZeros64() >> 3 // 8 - bytelen(x)
.buf[] = uint8( - uint64Size) // and then we subtract 8 to get -bytelen(x)
.b.Write(.buf[ : uint64Size+1])
}
func ( *encoderState) ( int64) {
var uint64
if < 0 {
= uint64(^<<1) | 1
} else {
= uint64( << 1)
}
.encodeUint()
}
type encOp func(i *encInstr, state *encoderState, v reflect.Value)
func ( *encoderState) ( *encInstr) {
if != nil {
.encodeUint(uint64(.field - .fieldnum))
.fieldnum = .field
}
}
func ( *encInstr, *encoderState, reflect.Value) {
:= .Bool()
if || .sendZero {
.update()
if {
.encodeUint(1)
} else {
.encodeUint(0)
}
}
}
func ( *encInstr, *encoderState, reflect.Value) {
:= .Uint()
if != 0 || .sendZero {
.update()
.encodeUint()
}
}
func ( float64) uint64 {
:= math.Float64bits()
return bits.ReverseBytes64()
}
func ( *encInstr, *encoderState, reflect.Value) {
:= .Float()
if != 0 || .sendZero {
:= floatBits()
.update()
.encodeUint()
}
}
func ( *encInstr, *encoderState, reflect.Value) {
:= .Complex()
if != 0+0i || .sendZero {
:= floatBits(real())
:= floatBits(imag())
.update()
.encodeUint()
.encodeUint()
}
}
func ( *encInstr, *encoderState, reflect.Value) {
:= .String()
if len() > 0 || .sendZero {
.update()
.encodeUint(uint64(len()))
.b.WriteString()
}
}
func ( *encInstr, *encoderState, reflect.Value) {
.encodeUint(0)
}
type encEngine struct {
instr []encInstr
}
const singletonField = 0
func ( *Encoder) ( *encBuffer, *encEngine, reflect.Value) {
:= .newEncoderState()
defer .freeEncoderState()
.sendZero = true
:= &.instr[singletonField]
if .indir > 0 {
= encIndirect(, .indir)
}
if valid() {
.op(, , )
}
}
func ( *Encoder) ( *encBuffer, reflect.Value, , encOp, , int) {
:= .newEncoderState()
.fieldnum = -1
.sendZero = true
:= .MapKeys()
.encodeUint(uint64(len()))
for , := range {
encodeReflectValue(, , , )
encodeReflectValue(, .MapIndex(), , )
}
.freeEncoderState()
}
:= .Elem()
if .Kind() == reflect.Ptr && .IsNil() {
errorf("gob: cannot encode nil pointer of type %s inside interface", .Elem().Type())
}
:= .newEncoderState()
.fieldnum = -1
.sendZero = true
if .IsNil() {
.encodeUint(0)
return
}
:= userType(.Elem().Type())
, := concreteTypeToName.Load(.base)
if ! {
errorf("type not registered for interface: %s", .base)
}
:= .(string)
.encodeUint(uint64(len()))
.pushWriter()
:= encBufferPool.Get().(*encBuffer)
.Write(spaceForLength)
.encode(, , )
if .err != nil {
error_(.err)
}
.popWriter()
.writeMessage(, )
.Reset()
encBufferPool.Put()
if .err != nil {
error_(.err)
}
.freeEncoderState()
}
func ( reflect.Value) bool {
switch .Kind() {
case reflect.Array:
for := 0; < .Len(); ++ {
if !(.Index()) {
return false
}
}
return true
case reflect.Map, reflect.Slice, reflect.String:
return .Len() == 0
case reflect.Bool:
return !.Bool()
case reflect.Complex64, reflect.Complex128:
return .Complex() == 0
case reflect.Chan, reflect.Func, reflect.Interface, reflect.Ptr:
return .IsNil()
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return .Int() == 0
case reflect.Float32, reflect.Float64:
return .Float() == 0
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return .Uint() == 0
case reflect.Struct:
for := 0; < .NumField(); ++ {
if !(.Field()) {
return false
}
}
return true
}
panic("unknown type in isZero " + .Type().String())
}
var []byte
switch .externalEnc {
case xGob:
, = .Interface().(GobEncoder).GobEncode()
case xBinary:
, = .Interface().(encoding.BinaryMarshaler).MarshalBinary()
case xText:
, = .Interface().(encoding.TextMarshaler).MarshalText()
}
if != nil {
error_()
}
:= .newEncoderState()
.fieldnum = -1
.encodeUint(uint64(len()))
.b.Write()
.freeEncoderState()
}
var encOpTable = [...]encOp{
reflect.Bool: encBool,
reflect.Int: encInt,
reflect.Int8: encInt,
reflect.Int16: encInt,
reflect.Int32: encInt,
reflect.Int64: encInt,
reflect.Uint: encUint,
reflect.Uint8: encUint,
reflect.Uint16: encUint,
reflect.Uint32: encUint,
reflect.Uint64: encUint,
reflect.Uintptr: encUint,
reflect.Float32: encFloat,
reflect.Float64: encFloat,
reflect.Complex64: encComplex,
reflect.Complex128: encComplex,
reflect.String: encString,
}
if .externalEnc != 0 {
return gobEncodeOpFor()
, := (.Elem(), , )
:= encSliceHelper[.Elem().Kind()]
= func( *encInstr, *encoderState, reflect.Value) {
if !.sendZero && .Len() == 0 {
return
}
.update()
.enc.encodeArray(.b, , *, , .Len(), )
}
getEncEngine(userType(), )
:= mustGetTypeInfo()
= func( *encInstr, *encoderState, reflect.Value) {
func ( *userTypeInfo, map[*typeInfo]bool) *encEngine {
:= .base
:= new(encEngine)
:= make(map[reflect.Type]*encOp)
:= .base
if .externalEnc != 0 {
= .user
}
if .externalEnc == 0 && .Kind() == reflect.Struct {
for , := 0, 0; < .NumField(); ++ {
:= .Field()
if !isSent(&) {
continue
}
, := encOpFor(.Type, , )
.instr = append(.instr, encInstr{*, , .Index, })
++
}
if .NumField() > 0 && len(.instr) == 0 {
errorf("type %s has no exported fields", )
}
.instr = append(.instr, encInstr{encStructTerminator, 0, nil, 0})
} else {
.instr = make([]encInstr, 1)
, := encOpFor(, , )
.instr[0] = encInstr{*, singletonField, nil, }
}
return
}
func ( *userTypeInfo, map[*typeInfo]bool) *encEngine {
, := getTypeInfo()
if != nil {
error_()
}
, := .encoder.Load().(*encEngine)
if ! {
= buildEncEngine(, , )
}
return
}
if != nil && [] {
return nil
}
.encInit.Lock()
defer .encInit.Unlock()
, := .encoder.Load().(*encEngine)
if ! {
if == nil {
= make(map[*typeInfo]bool)
}
[] = true
= compileEnc(, )
.encoder.Store()
}
return
}
func ( *Encoder) ( *encBuffer, reflect.Value, *userTypeInfo) {
defer catchError(&.err)
:= getEncEngine(, nil)
:= .indir
if .externalEnc != 0 {
= int(.encIndir)
}
for := 0; < ; ++ {
= reflect.Indirect()
}
if .externalEnc == 0 && .Type().Kind() == reflect.Struct {
.encodeStruct(, , )
} else {
.encodeSingle(, , )
}
![]() |
The pages are generated with Golds v0.3.2-preview. (GOOS=darwin 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 @Go100and1 (reachable from the left QR code) to get the latest news of Golds. |