Left: | ||
Right: |
OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 } |
OLD | NEW |