Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(629)

Side by Side Diff: src/pkg/encoding/gob/encode.go

Issue 12681044: code review 12681044: encoding/gob: support new generic interfaces in package... (Closed)
Patch Set: diff -r 00b5a40ae411 https://code.google.com/p/go/ Created 10 years, 7 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/pkg/encoding/gob/doc.go ('k') | src/pkg/encoding/gob/encoder.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2009 The Go Authors. All rights reserved. 1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style 2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file. 3 // license that can be found in the LICENSE file.
4 4
5 package gob 5 package gob
6 6
7 import ( 7 import (
8 "bytes" 8 "bytes"
9 "encoding"
9 "math" 10 "math"
10 "reflect" 11 "reflect"
11 "unsafe" 12 "unsafe"
12 ) 13 )
13 14
14 const uint64Size = int(unsafe.Sizeof(uint64(0))) 15 const uint64Size = int(unsafe.Sizeof(uint64(0)))
15 16
16 // encoderState is the global execution state of an instance of the encoder. 17 // encoderState is the global execution state of an instance of the encoder.
17 // Field numbers are delta encoded and always increase. The field 18 // Field numbers are delta encoded and always increase. The field
18 // number is initialized to -1 so 0 comes out as delta(1). A delta of 19 // number is initialized to -1 so 0 comes out as delta(1). A delta of
(...skipping 485 matching lines...) Expand 10 before | Expand all | Expand 10 after
504 return false 505 return false
505 } 506 }
506 } 507 }
507 return true 508 return true
508 } 509 }
509 panic("unknown type in isZero " + val.Type().String()) 510 panic("unknown type in isZero " + val.Type().String())
510 } 511 }
511 512
512 // encGobEncoder encodes a value that implements the GobEncoder interface. 513 // encGobEncoder encodes a value that implements the GobEncoder interface.
513 // The data is sent as a byte array. 514 // The data is sent as a byte array.
514 func (enc *Encoder) encodeGobEncoder(b *bytes.Buffer, v reflect.Value) { 515 func (enc *Encoder) encodeGobEncoder(b *bytes.Buffer, ut *userTypeInfo, v reflec t.Value) {
515 // TODO: should we catch panics from the called method? 516 // TODO: should we catch panics from the called method?
516 » // We know it's a GobEncoder, so just call the method directly. 517
517 » data, err := v.Interface().(GobEncoder).GobEncode() 518 » var data []byte
519 » var err error
520 » // We know it's one of these.
521 » switch ut.externalEnc {
522 » case xGob:
523 » » data, err = v.Interface().(GobEncoder).GobEncode()
524 » case xBinary:
525 » » data, err = v.Interface().(encoding.BinaryMarshaler).MarshalBina ry()
526 » case xText:
527 » » data, err = v.Interface().(encoding.TextMarshaler).MarshalText()
528 » }
518 if err != nil { 529 if err != nil {
519 error_(err) 530 error_(err)
520 } 531 }
521 state := enc.newEncoderState(b) 532 state := enc.newEncoderState(b)
522 state.fieldnum = -1 533 state.fieldnum = -1
523 state.encodeUint(uint64(len(data))) 534 state.encodeUint(uint64(len(data)))
524 state.b.Write(data) 535 state.b.Write(data)
525 enc.freeEncoderState(state) 536 enc.freeEncoderState(state)
526 } 537 }
527 538
(...skipping 15 matching lines...) Expand all
543 reflect.Complex64: encComplex64, 554 reflect.Complex64: encComplex64,
544 reflect.Complex128: encComplex128, 555 reflect.Complex128: encComplex128,
545 reflect.String: encString, 556 reflect.String: encString,
546 } 557 }
547 558
548 // encOpFor returns (a pointer to) the encoding op for the base type under rt an d 559 // encOpFor returns (a pointer to) the encoding op for the base type under rt an d
549 // the indirection count to reach it. 560 // the indirection count to reach it.
550 func (enc *Encoder) encOpFor(rt reflect.Type, inProgress map[reflect.Type]*encOp ) (*encOp, int) { 561 func (enc *Encoder) encOpFor(rt reflect.Type, inProgress map[reflect.Type]*encOp ) (*encOp, int) {
551 ut := userType(rt) 562 ut := userType(rt)
552 // If the type implements GobEncoder, we handle it without further proce ssing. 563 // If the type implements GobEncoder, we handle it without further proce ssing.
553 » if ut.isGobEncoder { 564 » if ut.externalEnc != 0 {
554 return enc.gobEncodeOpFor(ut) 565 return enc.gobEncodeOpFor(ut)
555 } 566 }
556 // If this type is already in progress, it's a recursive type (e.g. map[ string]*T). 567 // If this type is already in progress, it's a recursive type (e.g. map[ string]*T).
557 // Return the pointer to the op we're already building. 568 // Return the pointer to the op we're already building.
558 if opPtr := inProgress[rt]; opPtr != nil { 569 if opPtr := inProgress[rt]; opPtr != nil {
559 return opPtr, ut.indir 570 return opPtr, ut.indir
560 } 571 }
561 typ := ut.base 572 typ := ut.base
562 indir := ut.indir 573 indir := ut.indir
563 k := typ.Kind() 574 k := typ.Kind()
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
654 if ut.encIndir == -1 { 665 if ut.encIndir == -1 {
655 // Need to climb up one level to turn value into pointer . 666 // Need to climb up one level to turn value into pointer .
656 v = reflect.NewAt(rt, unsafe.Pointer(&p)).Elem() 667 v = reflect.NewAt(rt, unsafe.Pointer(&p)).Elem()
657 } else { 668 } else {
658 v = reflect.NewAt(rt, p).Elem() 669 v = reflect.NewAt(rt, p).Elem()
659 } 670 }
660 if !state.sendZero && isZero(v) { 671 if !state.sendZero && isZero(v) {
661 return 672 return
662 } 673 }
663 state.update(i) 674 state.update(i)
664 » » state.enc.encodeGobEncoder(state.b, v) 675 » » state.enc.encodeGobEncoder(state.b, ut, v)
665 } 676 }
666 return &op, int(ut.encIndir) // encIndir: op will get called with p == a ddress of receiver. 677 return &op, int(ut.encIndir) // encIndir: op will get called with p == a ddress of receiver.
667 } 678 }
668 679
669 // compileEnc returns the engine to compile the type. 680 // compileEnc returns the engine to compile the type.
670 func (enc *Encoder) compileEnc(ut *userTypeInfo) *encEngine { 681 func (enc *Encoder) compileEnc(ut *userTypeInfo) *encEngine {
671 srt := ut.base 682 srt := ut.base
672 engine := new(encEngine) 683 engine := new(encEngine)
673 seen := make(map[reflect.Type]*encOp) 684 seen := make(map[reflect.Type]*encOp)
674 rt := ut.base 685 rt := ut.base
675 » if ut.isGobEncoder { 686 » if ut.externalEnc != 0 {
676 rt = ut.user 687 rt = ut.user
677 } 688 }
678 » if !ut.isGobEncoder && 689 » if ut.externalEnc == 0 &&
679 srt.Kind() == reflect.Struct { 690 srt.Kind() == reflect.Struct {
680 for fieldNum, wireFieldNum := 0, 0; fieldNum < srt.NumField(); f ieldNum++ { 691 for fieldNum, wireFieldNum := 0, 0; fieldNum < srt.NumField(); f ieldNum++ {
681 f := srt.Field(fieldNum) 692 f := srt.Field(fieldNum)
682 if !isExported(f.Name) { 693 if !isExported(f.Name) {
683 continue 694 continue
684 } 695 }
685 op, indir := enc.encOpFor(f.Type, seen) 696 op, indir := enc.encOpFor(f.Type, seen)
686 engine.instr = append(engine.instr, encInstr{*op, wireFi eldNum, indir, uintptr(f.Offset)}) 697 engine.instr = append(engine.instr, encInstr{*op, wireFi eldNum, indir, uintptr(f.Offset)})
687 wireFieldNum++ 698 wireFieldNum++
688 } 699 }
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
729 func (enc *Encoder) lockAndGetEncEngine(ut *userTypeInfo) *encEngine { 740 func (enc *Encoder) lockAndGetEncEngine(ut *userTypeInfo) *encEngine {
730 typeLock.Lock() 741 typeLock.Lock()
731 defer typeLock.Unlock() 742 defer typeLock.Unlock()
732 return enc.getEncEngine(ut) 743 return enc.getEncEngine(ut)
733 } 744 }
734 745
735 func (enc *Encoder) encode(b *bytes.Buffer, value reflect.Value, ut *userTypeInf o) { 746 func (enc *Encoder) encode(b *bytes.Buffer, value reflect.Value, ut *userTypeInf o) {
736 defer catchError(&enc.err) 747 defer catchError(&enc.err)
737 engine := enc.lockAndGetEncEngine(ut) 748 engine := enc.lockAndGetEncEngine(ut)
738 indir := ut.indir 749 indir := ut.indir
739 » if ut.isGobEncoder { 750 » if ut.externalEnc != 0 {
740 indir = int(ut.encIndir) 751 indir = int(ut.encIndir)
741 } 752 }
742 for i := 0; i < indir; i++ { 753 for i := 0; i < indir; i++ {
743 value = reflect.Indirect(value) 754 value = reflect.Indirect(value)
744 } 755 }
745 » if !ut.isGobEncoder && value.Type().Kind() == reflect.Struct { 756 » if ut.externalEnc == 0 && value.Type().Kind() == reflect.Struct {
746 enc.encodeStruct(b, engine, unsafeAddr(value)) 757 enc.encodeStruct(b, engine, unsafeAddr(value))
747 } else { 758 } else {
748 enc.encodeSingle(b, engine, unsafeAddr(value)) 759 enc.encodeSingle(b, engine, unsafeAddr(value))
749 } 760 }
750 } 761 }
OLDNEW
« no previous file with comments | « src/pkg/encoding/gob/doc.go ('k') | src/pkg/encoding/gob/encoder.go » ('j') | no next file with comments »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b