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

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

Issue 12681044: code review 12681044: encoding/gob: support new generic interfaces in package... (Closed)
Patch Set: diff -r b1c9e72c2ca3 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
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 "encoding"
8 "errors" 9 "errors"
9 "fmt" 10 "fmt"
10 "os" 11 "os"
11 "reflect" 12 "reflect"
12 "sync" 13 "sync"
13 "unicode" 14 "unicode"
14 "unicode/utf8" 15 "unicode/utf8"
15 ) 16 )
16 17
17 // userTypeInfo stores the information associated with a type the user has hande d 18 // userTypeInfo stores the information associated with a type the user has hande d
18 // to the package. It's computed once and stored in a map keyed by reflection 19 // to the package. It's computed once and stored in a map keyed by reflection
19 // type. 20 // type.
20 type userTypeInfo struct { 21 type userTypeInfo struct {
21 » user reflect.Type // the type the user handed us 22 » user reflect.Type // the type the user handed us
22 » base reflect.Type // the base type after all indirections 23 » base reflect.Type // the base type after all indirections
23 » indir int // number of indirections to reach the base ty pe 24 » indir int // number of indirections to reach the base type
24 » isGobEncoder bool // does the type implement GobEncoder? 25 » isGobEncoder bool // does the type implement GobEncoder?
25 » isGobDecoder bool // does the type implement GobDecoder? 26 » isGobDecoder bool // does the type implement GobDecoder?
26 » encIndir int8 // number of indirections to reach the receive r type; may be negative 27 » isBinaryMarshaler bool // does the type implement encoding.Bin aryMarshaler?
27 » decIndir int8 // number of indirections to reach the receive r type; may be negative 28 » isBinaryUnmarshaler bool // does the type implement encoding.Bin aryUnmarshaler?
29 » isTextMarshaler bool // does the type implement encoding.Tex tMarshaler?
30 » isTextUnmarshaler bool // does the type implement encoding.Tex tUnmarshaler?
31 » encIndir int8 // number of indirections to reach the receiver type; may be negative
r 2013/08/10 21:53:35 with six booleans and the usage pattern i see, i s
rsc 2013/08/13 14:24:37 Done.
32 » decIndir int8 // number of indirections to reach the receiver type; may be negative
28 } 33 }
29 34
30 var ( 35 var (
31 // Protected by an RWMutex because we read it a lot and write 36 // Protected by an RWMutex because we read it a lot and write
32 // it only when we see a new type, typically when compiling. 37 // it only when we see a new type, typically when compiling.
33 userTypeLock sync.RWMutex 38 userTypeLock sync.RWMutex
34 userTypeCache = make(map[reflect.Type]*userTypeInfo) 39 userTypeCache = make(map[reflect.Type]*userTypeInfo)
35 ) 40 )
36 41
37 // validType returns, and saves, the information associated with user-provided t ype rt. 42 // validType returns, and saves, the information associated with user-provided t ype rt.
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
69 if ut.base == slowpoke { // ut.base lapped slowpoke 74 if ut.base == slowpoke { // ut.base lapped slowpoke
70 // recursive pointer type. 75 // recursive pointer type.
71 return nil, errors.New("can't represent recursive pointe r type " + ut.base.String()) 76 return nil, errors.New("can't represent recursive pointe r type " + ut.base.String())
72 } 77 }
73 if ut.indir%2 == 0 { 78 if ut.indir%2 == 0 {
74 slowpoke = slowpoke.Elem() 79 slowpoke = slowpoke.Elem()
75 } 80 }
76 ut.indir++ 81 ut.indir++
77 } 82 }
78 ut.isGobEncoder, ut.encIndir = implementsInterface(ut.user, gobEncoderIn terfaceType) 83 ut.isGobEncoder, ut.encIndir = implementsInterface(ut.user, gobEncoderIn terfaceType)
84 if !ut.isGobEncoder {
85 ut.isBinaryMarshaler, ut.encIndir = implementsInterface(ut.user, binaryMarshalerInterfaceType)
86 if !ut.isBinaryMarshaler {
87 ut.isTextMarshaler, ut.encIndir = implementsInterface(ut .user, textMarshalerInterfaceType)
88 }
89 }
79 ut.isGobDecoder, ut.decIndir = implementsInterface(ut.user, gobDecoderIn terfaceType) 90 ut.isGobDecoder, ut.decIndir = implementsInterface(ut.user, gobDecoderIn terfaceType)
91 if !ut.isGobDecoder {
92 ut.isBinaryUnmarshaler, ut.decIndir = implementsInterface(ut.use r, binaryUnmarshalerInterfaceType)
93 if !ut.isBinaryUnmarshaler {
94 ut.isTextUnmarshaler, ut.decIndir = implementsInterface( ut.user, textUnmarshalerInterfaceType)
95 }
96 }
80 userTypeCache[rt] = ut 97 userTypeCache[rt] = ut
81 return 98 return
82 } 99 }
83 100
84 var ( 101 var (
85 » gobEncoderInterfaceType = reflect.TypeOf((*GobEncoder)(nil)).Elem() 102 » gobEncoderInterfaceType = reflect.TypeOf((*GobEncoder)(nil)).Elem ()
86 » gobDecoderInterfaceType = reflect.TypeOf((*GobDecoder)(nil)).Elem() 103 » gobDecoderInterfaceType = reflect.TypeOf((*GobDecoder)(nil)).Elem ()
104 » binaryMarshalerInterfaceType = reflect.TypeOf((*encoding.BinaryMarshal er)(nil)).Elem()
105 » binaryUnmarshalerInterfaceType = reflect.TypeOf((*encoding.BinaryUnmarsh aler)(nil)).Elem()
106 » textMarshalerInterfaceType = reflect.TypeOf((*encoding.TextMarshaler )(nil)).Elem()
107 » textUnmarshalerInterfaceType = reflect.TypeOf((*encoding.TextUnmarshal er)(nil)).Elem()
87 ) 108 )
88 109
89 // implementsInterface reports whether the type implements the 110 // implementsInterface reports whether the type implements the
90 // gobEncoder/gobDecoder interface. 111 // gobEncoder/gobDecoder interface.
91 // It also returns the number of indirections required to get to the 112 // It also returns the number of indirections required to get to the
92 // implementation. 113 // implementation.
93 func implementsInterface(typ, gobEncDecType reflect.Type) (success bool, indir i nt8) { 114 func implementsInterface(typ, gobEncDecType reflect.Type) (success bool, indir i nt8) {
94 if typ == nil { 115 if typ == nil {
95 return 116 return
96 } 117 }
(...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after
405 return s 426 return s
406 } 427 }
407 428
408 // newTypeObject allocates a gobType for the reflection type rt. 429 // newTypeObject allocates a gobType for the reflection type rt.
409 // Unless ut represents a GobEncoder, rt should be the base type 430 // Unless ut represents a GobEncoder, rt should be the base type
410 // of ut. 431 // of ut.
411 // This is only called from the encoding side. The decoding side 432 // This is only called from the encoding side. The decoding side
412 // works through typeIds and userTypeInfos alone. 433 // works through typeIds and userTypeInfos alone.
413 func newTypeObject(name string, ut *userTypeInfo, rt reflect.Type) (gobType, err or) { 434 func newTypeObject(name string, ut *userTypeInfo, rt reflect.Type) (gobType, err or) {
414 // Does this type implement GobEncoder? 435 // Does this type implement GobEncoder?
415 » if ut.isGobEncoder { 436 » if ut.isGobEncoder || ut.isBinaryMarshaler || ut.isTextMarshaler {
416 return newGobEncoderType(name), nil 437 return newGobEncoderType(name), nil
417 } 438 }
418 var err error 439 var err error
419 var type0, type1 gobType 440 var type0, type1 gobType
420 defer func() { 441 defer func() {
421 if err != nil { 442 if err != nil {
422 delete(types, rt) 443 delete(types, rt)
423 } 444 }
424 }() 445 }()
425 // Install the top-level type before the subtypes (e.g. struct before 446 // Install the top-level type before the subtypes (e.g. struct before
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
586 // However, the very first time we send the value, we first send the pair 607 // However, the very first time we send the value, we first send the pair
587 // (-id, wireType). 608 // (-id, wireType).
588 // For bootstrapping purposes, we assume that the recipient knows how 609 // For bootstrapping purposes, we assume that the recipient knows how
589 // to decode a wireType; it is exactly the wireType struct here, interpreted 610 // to decode a wireType; it is exactly the wireType struct here, interpreted
590 // using the gob rules for sending a structure, except that we assume the 611 // using the gob rules for sending a structure, except that we assume the
591 // ids for wireType and structType etc. are known. The relevant pieces 612 // ids for wireType and structType etc. are known. The relevant pieces
592 // are built in encode.go's init() function. 613 // are built in encode.go's init() function.
593 // To maintain binary compatibility, if you extend this type, always put 614 // To maintain binary compatibility, if you extend this type, always put
594 // the new fields last. 615 // the new fields last.
595 type wireType struct { 616 type wireType struct {
596 » ArrayT *arrayType 617 » ArrayT *arrayType
597 » SliceT *sliceType 618 » SliceT *sliceType
598 » StructT *structType 619 » StructT *structType
599 » MapT *mapType 620 » MapT *mapType
600 » GobEncoderT *gobEncoderType 621 » GobEncoderT *gobEncoderType
622 » BinaryMarshalerT *gobEncoderType
623 » TextMarshalerT *gobEncoderType
601 } 624 }
602 625
603 func (w *wireType) string() string { 626 func (w *wireType) string() string {
604 const unknown = "unknown type" 627 const unknown = "unknown type"
605 if w == nil { 628 if w == nil {
606 return unknown 629 return unknown
607 } 630 }
608 switch { 631 switch {
609 case w.ArrayT != nil: 632 case w.ArrayT != nil:
610 return w.ArrayT.Name 633 return w.ArrayT.Name
611 case w.SliceT != nil: 634 case w.SliceT != nil:
612 return w.SliceT.Name 635 return w.SliceT.Name
613 case w.StructT != nil: 636 case w.StructT != nil:
614 return w.StructT.Name 637 return w.StructT.Name
615 case w.MapT != nil: 638 case w.MapT != nil:
616 return w.MapT.Name 639 return w.MapT.Name
617 case w.GobEncoderT != nil: 640 case w.GobEncoderT != nil:
618 return w.GobEncoderT.Name 641 return w.GobEncoderT.Name
642 case w.BinaryMarshalerT != nil:
643 return w.BinaryMarshalerT.Name
644 case w.TextMarshalerT != nil:
645 return w.TextMarshalerT.Name
619 } 646 }
620 return unknown 647 return unknown
621 } 648 }
622 649
623 type typeInfo struct { 650 type typeInfo struct {
624 id typeId 651 id typeId
625 encoder *encEngine 652 encoder *encEngine
626 wire *wireType 653 wire *wireType
627 } 654 }
628 655
629 var typeInfoMap = make(map[reflect.Type]*typeInfo) // protected by typeLock 656 var typeInfoMap = make(map[reflect.Type]*typeInfo) // protected by typeLock
630 657
631 // typeLock must be held. 658 // typeLock must be held.
632 func getTypeInfo(ut *userTypeInfo) (*typeInfo, error) { 659 func getTypeInfo(ut *userTypeInfo) (*typeInfo, error) {
633 rt := ut.base 660 rt := ut.base
634 » if ut.isGobEncoder { 661 » if ut.isGobEncoder || ut.isBinaryMarshaler || ut.isTextMarshaler {
635 // We want the user type, not the base type. 662 // We want the user type, not the base type.
636 rt = ut.user 663 rt = ut.user
637 } 664 }
638 info, ok := typeInfoMap[rt] 665 info, ok := typeInfoMap[rt]
639 if ok { 666 if ok {
640 return info, nil 667 return info, nil
641 } 668 }
642 info = new(typeInfo) 669 info = new(typeInfo)
643 gt, err := getBaseType(rt.Name(), rt) 670 gt, err := getBaseType(rt.Name(), rt)
644 if err != nil { 671 if err != nil {
645 return nil, err 672 return nil, err
646 } 673 }
647 info.id = gt.id() 674 info.id = gt.id()
648 675
649 » if ut.isGobEncoder { 676 » if ut.isGobEncoder || ut.isBinaryMarshaler || ut.isTextMarshaler {
650 userType, err := getType(rt.Name(), ut, rt) 677 userType, err := getType(rt.Name(), ut, rt)
651 if err != nil { 678 if err != nil {
652 return nil, err 679 return nil, err
653 } 680 }
654 » » info.wire = &wireType{GobEncoderT: userType.id().gobType().(*gob EncoderType)} 681 » » gt := userType.id().gobType().(*gobEncoderType)
682 » » switch {
683 » » case ut.isGobEncoder:
684 » » » info.wire = &wireType{GobEncoderT: gt}
685 » » case ut.isBinaryMarshaler:
686 » » » info.wire = &wireType{BinaryMarshalerT: gt}
687 » » case ut.isTextMarshaler:
688 » » » info.wire = &wireType{TextMarshalerT: gt}
689 » » }
655 typeInfoMap[ut.user] = info 690 typeInfoMap[ut.user] = info
656 return info, nil 691 return info, nil
657 } 692 }
658 693
659 t := info.id.gobType() 694 t := info.id.gobType()
660 switch typ := rt; typ.Kind() { 695 switch typ := rt; typ.Kind() {
661 case reflect.Array: 696 case reflect.Array:
662 info.wire = &wireType{ArrayT: t.(*arrayType)} 697 info.wire = &wireType{ArrayT: t.(*arrayType)}
663 case reflect.Map: 698 case reflect.Map:
664 info.wire = &wireType{MapT: t.(*mapType)} 699 info.wire = &wireType{MapT: t.(*mapType)}
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
817 Register([]uint32(nil)) 852 Register([]uint32(nil))
818 Register([]uint64(nil)) 853 Register([]uint64(nil))
819 Register([]float32(nil)) 854 Register([]float32(nil))
820 Register([]float64(nil)) 855 Register([]float64(nil))
821 Register([]complex64(nil)) 856 Register([]complex64(nil))
822 Register([]complex128(nil)) 857 Register([]complex128(nil))
823 Register([]uintptr(nil)) 858 Register([]uintptr(nil))
824 Register([]bool(nil)) 859 Register([]bool(nil))
825 Register([]string(nil)) 860 Register([]string(nil))
826 } 861 }
OLDNEW
« src/pkg/encoding/gob/doc.go ('K') | « src/pkg/encoding/gob/gobencdec_test.go ('k') | no next file » | no next file with comments »

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