summaryrefslogtreecommitdiffstats
path: root/libgo/go/gob/decoder.go
blob: 664001a4b21e0bf7ba4ada7e9390a955e1d26b2d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package gob

import (
	"bytes"
	"io"
	"os"
	"reflect"
	"sync"
)

// A Decoder manages the receipt of type and data information read from the
// remote side of a connection.
type Decoder struct {
	mutex        sync.Mutex                              // each item must be received atomically
	r            io.Reader                               // source of the data
	wireType     map[typeId]*wireType                    // map from remote ID to local description
	decoderCache map[reflect.Type]map[typeId]**decEngine // cache of compiled engines
	ignorerCache map[typeId]**decEngine                  // ditto for ignored objects
	state        *decodeState                            // reads data from in-memory buffer
	countState   *decodeState                            // reads counts from wire
	buf          []byte
	countBuf     [9]byte // counts may be uint64s (unlikely!), require 9 bytes
	byteBuffer   *bytes.Buffer
	err          os.Error
}

// NewDecoder returns a new decoder that reads from the io.Reader.
func NewDecoder(r io.Reader) *Decoder {
	dec := new(Decoder)
	dec.r = r
	dec.wireType = make(map[typeId]*wireType)
	dec.state = newDecodeState(dec, &dec.byteBuffer) // buffer set in Decode()
	dec.decoderCache = make(map[reflect.Type]map[typeId]**decEngine)
	dec.ignorerCache = make(map[typeId]**decEngine)

	return dec
}

// recvType loads the definition of a type and reloads the Decoder's buffer.
func (dec *Decoder) recvType(id typeId) {
	// Have we already seen this type?  That's an error
	if dec.wireType[id] != nil {
		dec.err = os.ErrorString("gob: duplicate type received")
		return
	}

	// Type:
	wire := new(wireType)
	dec.err = dec.decode(tWireType, reflect.NewValue(wire))
	if dec.err != nil {
		return
	}
	// Remember we've seen this type.
	dec.wireType[id] = wire

	// Load the next parcel.
	dec.recv()
}

// Decode reads the next value from the connection and stores
// it in the data represented by the empty interface value.
// The value underlying e must be the correct type for the next
// data item received, and must be a pointer.
func (dec *Decoder) Decode(e interface{}) os.Error {
	value := reflect.NewValue(e)
	// If e represents a value as opposed to a pointer, the answer won't
	// get back to the caller.  Make sure it's a pointer.
	if value.Type().Kind() != reflect.Ptr {
		dec.err = os.ErrorString("gob: attempt to decode into a non-pointer")
		return dec.err
	}
	return dec.DecodeValue(value)
}

// recv reads the next count-delimited item from the input. It is the converse
// of Encoder.send.
func (dec *Decoder) recv() {
	// Read a count.
	var nbytes uint64
	nbytes, dec.err = decodeUintReader(dec.r, dec.countBuf[0:])
	if dec.err != nil {
		return
	}
	// Allocate the buffer.
	if nbytes > uint64(len(dec.buf)) {
		dec.buf = make([]byte, nbytes+1000)
	}
	dec.byteBuffer = bytes.NewBuffer(dec.buf[0:nbytes])

	// Read the data
	_, dec.err = io.ReadFull(dec.r, dec.buf[0:nbytes])
	if dec.err != nil {
		if dec.err == os.EOF {
			dec.err = io.ErrUnexpectedEOF
		}
		return
	}
}

// decodeValueFromBuffer grabs the next value from the input. The Decoder's
// buffer already contains data.  If the next item in the buffer is a type
// descriptor, it may be necessary to reload the buffer, but recvType does that.
func (dec *Decoder) decodeValueFromBuffer(value reflect.Value, ignoreInterfaceValue, countPresent bool) {
	for dec.state.b.Len() > 0 {
		// Receive a type id.
		id := typeId(dec.state.decodeInt())

		// Is it a new type?
		if id < 0 { // 0 is the error state, handled above
			// If the id is negative, we have a type.
			dec.recvType(-id)
			if dec.err != nil {
				break
			}
			continue
		}

		// Make sure the type has been defined already or is a builtin type (for
		// top-level singleton values).
		if dec.wireType[id] == nil && builtinIdToType[id] == nil {
			dec.err = errBadType
			break
		}
		// An interface value is preceded by a byte count.
		if countPresent {
			count := int(dec.state.decodeUint())
			if ignoreInterfaceValue {
				// An interface value is preceded by a byte count. Just skip that many bytes.
				dec.state.b.Next(int(count))
				break
			}
			// Otherwise fall through and decode it.
		}
		dec.err = dec.decode(id, value)
		break
	}
}

// DecodeValue reads the next value from the connection and stores
// it in the data represented by the reflection value.
// The value must be the correct type for the next
// data item received.
func (dec *Decoder) DecodeValue(value reflect.Value) os.Error {
	// Make sure we're single-threaded through here.
	dec.mutex.Lock()
	defer dec.mutex.Unlock()

	dec.err = nil
	dec.recv()
	if dec.err != nil {
		return dec.err
	}
	dec.decodeValueFromBuffer(value, false, false)
	return dec.err
}

// If debug.go is compiled into the program , debugFunc prints a human-readable
// representation of the gob data read from r by calling that file's Debug function.
// Otherwise it is nil.
var debugFunc func(io.Reader)
OpenPOWER on IntegriCloud