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 "math" | 9 "math" |
10 "reflect" | 10 "reflect" |
(...skipping 507 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
518 typ := ut.base | 518 typ := ut.base |
519 indir := ut.indir | 519 indir := ut.indir |
520 k := typ.Kind() | 520 k := typ.Kind() |
521 var op encOp | 521 var op encOp |
522 if int(k) < len(encOpTable) { | 522 if int(k) < len(encOpTable) { |
523 op = encOpTable[k] | 523 op = encOpTable[k] |
524 } | 524 } |
525 if op == nil { | 525 if op == nil { |
526 inProgress[rt] = &op | 526 inProgress[rt] = &op |
527 // Special cases | 527 // Special cases |
528 » » switch t := typ.(type) { | 528 » » switch t := typ; t.Kind() { |
529 » » case *reflect.SliceType: | 529 » » case reflect.Slice: |
530 if t.Elem().Kind() == reflect.Uint8 { | 530 if t.Elem().Kind() == reflect.Uint8 { |
531 op = encUint8Array | 531 op = encUint8Array |
532 break | 532 break |
533 } | 533 } |
534 // Slices have a header; we decode it to find the underl
ying array. | 534 // Slices have a header; we decode it to find the underl
ying array. |
535 elemOp, indir := enc.encOpFor(t.Elem(), inProgress) | 535 elemOp, indir := enc.encOpFor(t.Elem(), inProgress) |
536 op = func(i *encInstr, state *encoderState, p unsafe.Poi
nter) { | 536 op = func(i *encInstr, state *encoderState, p unsafe.Poi
nter) { |
537 slice := (*reflect.SliceHeader)(p) | 537 slice := (*reflect.SliceHeader)(p) |
538 if !state.sendZero && slice.Len == 0 { | 538 if !state.sendZero && slice.Len == 0 { |
539 return | 539 return |
540 } | 540 } |
541 state.update(i) | 541 state.update(i) |
542 state.enc.encodeArray(state.b, slice.Data, *elem
Op, t.Elem().Size(), indir, int(slice.Len)) | 542 state.enc.encodeArray(state.b, slice.Data, *elem
Op, t.Elem().Size(), indir, int(slice.Len)) |
543 } | 543 } |
544 » » case *reflect.ArrayType: | 544 » » case reflect.Array: |
545 // True arrays have size in the type. | 545 // True arrays have size in the type. |
546 elemOp, indir := enc.encOpFor(t.Elem(), inProgress) | 546 elemOp, indir := enc.encOpFor(t.Elem(), inProgress) |
547 op = func(i *encInstr, state *encoderState, p unsafe.Poi
nter) { | 547 op = func(i *encInstr, state *encoderState, p unsafe.Poi
nter) { |
548 state.update(i) | 548 state.update(i) |
549 state.enc.encodeArray(state.b, uintptr(p), *elem
Op, t.Elem().Size(), indir, t.Len()) | 549 state.enc.encodeArray(state.b, uintptr(p), *elem
Op, t.Elem().Size(), indir, t.Len()) |
550 } | 550 } |
551 » » case *reflect.MapType: | 551 » » case reflect.Map: |
552 keyOp, keyIndir := enc.encOpFor(t.Key(), inProgress) | 552 keyOp, keyIndir := enc.encOpFor(t.Key(), inProgress) |
553 elemOp, elemIndir := enc.encOpFor(t.Elem(), inProgress) | 553 elemOp, elemIndir := enc.encOpFor(t.Elem(), inProgress) |
554 op = func(i *encInstr, state *encoderState, p unsafe.Poi
nter) { | 554 op = func(i *encInstr, state *encoderState, p unsafe.Poi
nter) { |
555 // Maps cannot be accessed by moving addresses a
round the way | 555 // Maps cannot be accessed by moving addresses a
round the way |
556 // that slices etc. can. We must recover a full
reflection value for | 556 // that slices etc. can. We must recover a full
reflection value for |
557 // the iteration. | 557 // the iteration. |
558 v := reflect.NewValue(unsafe.Unreflect(t, unsafe
.Pointer(p))) | 558 v := reflect.NewValue(unsafe.Unreflect(t, unsafe
.Pointer(p))) |
559 mv := reflect.Indirect(v).(*reflect.MapValue) | 559 mv := reflect.Indirect(v).(*reflect.MapValue) |
560 if !state.sendZero && mv.Len() == 0 { | 560 if !state.sendZero && mv.Len() == 0 { |
561 return | 561 return |
562 } | 562 } |
563 state.update(i) | 563 state.update(i) |
564 state.enc.encodeMap(state.b, mv, *keyOp, *elemOp
, keyIndir, elemIndir) | 564 state.enc.encodeMap(state.b, mv, *keyOp, *elemOp
, keyIndir, elemIndir) |
565 } | 565 } |
566 » » case *reflect.StructType: | 566 » » case reflect.Struct: |
567 // Generate a closure that calls out to the engine for t
he nested type. | 567 // Generate a closure that calls out to the engine for t
he nested type. |
568 enc.getEncEngine(userType(typ)) | 568 enc.getEncEngine(userType(typ)) |
569 info := mustGetTypeInfo(typ) | 569 info := mustGetTypeInfo(typ) |
570 op = func(i *encInstr, state *encoderState, p unsafe.Poi
nter) { | 570 op = func(i *encInstr, state *encoderState, p unsafe.Poi
nter) { |
571 state.update(i) | 571 state.update(i) |
572 // indirect through info to delay evaluation for
recursive structs | 572 // indirect through info to delay evaluation for
recursive structs |
573 state.enc.encodeStruct(state.b, info.encoder, ui
ntptr(p)) | 573 state.enc.encodeStruct(state.b, info.encoder, ui
ntptr(p)) |
574 } | 574 } |
575 » » case *reflect.InterfaceType: | 575 » » case reflect.Interface: |
576 op = func(i *encInstr, state *encoderState, p unsafe.Poi
nter) { | 576 op = func(i *encInstr, state *encoderState, p unsafe.Poi
nter) { |
577 // Interfaces transmit the name and contents of
the concrete | 577 // Interfaces transmit the name and contents of
the concrete |
578 // value they contain. | 578 // value they contain. |
579 v := reflect.NewValue(unsafe.Unreflect(t, unsafe
.Pointer(p))) | 579 v := reflect.NewValue(unsafe.Unreflect(t, unsafe
.Pointer(p))) |
580 iv := reflect.Indirect(v).(*reflect.InterfaceVal
ue) | 580 iv := reflect.Indirect(v).(*reflect.InterfaceVal
ue) |
581 if !state.sendZero && (iv == nil || iv.IsNil())
{ | 581 if !state.sendZero && (iv == nil || iv.IsNil())
{ |
582 return | 582 return |
583 } | 583 } |
584 state.update(i) | 584 state.update(i) |
585 state.enc.encodeInterface(state.b, iv) | 585 state.enc.encodeInterface(state.b, iv) |
(...skipping 18 matching lines...) Expand all Loading... |
604 } | 604 } |
605 | 605 |
606 // gobEncodeOpFor returns the op for a type that is known to implement | 606 // gobEncodeOpFor returns the op for a type that is known to implement |
607 // GobEncoder. | 607 // GobEncoder. |
608 func (enc *Encoder) gobEncodeOpFor(ut *userTypeInfo) (*encOp, int) { | 608 func (enc *Encoder) gobEncodeOpFor(ut *userTypeInfo) (*encOp, int) { |
609 rt := ut.user | 609 rt := ut.user |
610 if ut.encIndir == -1 { | 610 if ut.encIndir == -1 { |
611 rt = reflect.PtrTo(rt) | 611 rt = reflect.PtrTo(rt) |
612 } else if ut.encIndir > 0 { | 612 } else if ut.encIndir > 0 { |
613 for i := int8(0); i < ut.encIndir; i++ { | 613 for i := int8(0); i < ut.encIndir; i++ { |
614 » » » rt = rt.(*reflect.PtrType).Elem() | 614 » » » rt = rt.Elem() |
615 } | 615 } |
616 } | 616 } |
617 var op encOp | 617 var op encOp |
618 op = func(i *encInstr, state *encoderState, p unsafe.Pointer) { | 618 op = func(i *encInstr, state *encoderState, p unsafe.Pointer) { |
619 var v reflect.Value | 619 var v reflect.Value |
620 if ut.encIndir == -1 { | 620 if ut.encIndir == -1 { |
621 // Need to climb up one level to turn value into pointer
. | 621 // Need to climb up one level to turn value into pointer
. |
622 v = reflect.NewValue(unsafe.Unreflect(rt, unsafe.Pointer
(&p))) | 622 v = reflect.NewValue(unsafe.Unreflect(rt, unsafe.Pointer
(&p))) |
623 } else { | 623 } else { |
624 v = reflect.NewValue(unsafe.Unreflect(rt, p)) | 624 v = reflect.NewValue(unsafe.Unreflect(rt, p)) |
625 } | 625 } |
626 state.update(i) | 626 state.update(i) |
627 state.enc.encodeGobEncoder(state.b, v, methodIndex(rt, gobEncode
MethodName)) | 627 state.enc.encodeGobEncoder(state.b, v, methodIndex(rt, gobEncode
MethodName)) |
628 } | 628 } |
629 return &op, int(ut.encIndir) // encIndir: op will get called with p == a
ddress of receiver. | 629 return &op, int(ut.encIndir) // encIndir: op will get called with p == a
ddress of receiver. |
630 } | 630 } |
631 | 631 |
632 // compileEnc returns the engine to compile the type. | 632 // compileEnc returns the engine to compile the type. |
633 func (enc *Encoder) compileEnc(ut *userTypeInfo) *encEngine { | 633 func (enc *Encoder) compileEnc(ut *userTypeInfo) *encEngine { |
634 » srt, isStruct := ut.base.(*reflect.StructType) | 634 » srt := ut.base |
635 engine := new(encEngine) | 635 engine := new(encEngine) |
636 seen := make(map[reflect.Type]*encOp) | 636 seen := make(map[reflect.Type]*encOp) |
637 rt := ut.base | 637 rt := ut.base |
638 if ut.isGobEncoder { | 638 if ut.isGobEncoder { |
639 rt = ut.user | 639 rt = ut.user |
640 } | 640 } |
641 » if !ut.isGobEncoder && isStruct { | 641 » if !ut.isGobEncoder && |
| 642 » » srt.Kind() == reflect.Struct { |
642 for fieldNum, wireFieldNum := 0, 0; fieldNum < srt.NumField(); f
ieldNum++ { | 643 for fieldNum, wireFieldNum := 0, 0; fieldNum < srt.NumField(); f
ieldNum++ { |
643 f := srt.Field(fieldNum) | 644 f := srt.Field(fieldNum) |
644 if !isExported(f.Name) { | 645 if !isExported(f.Name) { |
645 continue | 646 continue |
646 } | 647 } |
647 op, indir := enc.encOpFor(f.Type, seen) | 648 op, indir := enc.encOpFor(f.Type, seen) |
648 engine.instr = append(engine.instr, encInstr{*op, wireFi
eldNum, indir, uintptr(f.Offset)}) | 649 engine.instr = append(engine.instr, encInstr{*op, wireFi
eldNum, indir, uintptr(f.Offset)}) |
649 wireFieldNum++ | 650 wireFieldNum++ |
650 } | 651 } |
651 if srt.NumField() > 0 && len(engine.instr) == 0 { | 652 if srt.NumField() > 0 && len(engine.instr) == 0 { |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
692 } | 693 } |
693 for i := 0; i < indir; i++ { | 694 for i := 0; i < indir; i++ { |
694 value = reflect.Indirect(value) | 695 value = reflect.Indirect(value) |
695 } | 696 } |
696 if !ut.isGobEncoder && value.Type().Kind() == reflect.Struct { | 697 if !ut.isGobEncoder && value.Type().Kind() == reflect.Struct { |
697 enc.encodeStruct(b, engine, value.UnsafeAddr()) | 698 enc.encodeStruct(b, engine, value.UnsafeAddr()) |
698 } else { | 699 } else { |
699 enc.encodeSingle(b, engine, value.UnsafeAddr()) | 700 enc.encodeSingle(b, engine, value.UnsafeAddr()) |
700 } | 701 } |
701 } | 702 } |
OLD | NEW |