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 "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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 } |
OLD | NEW |