summaryrefslogtreecommitdiff
path: root/src/pkg/gob/decoder.go
blob: cf16433eb6add9514645c675317df1d53222cca3 (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
// 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
}

// 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(nil) // buffer set in Decode(); rest is unimportant
	dec.decoderCache = make(map[reflect.Type]map[typeId]**decEngine)
	dec.ignorerCache = make(map[typeId]**decEngine)

	return dec
}

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

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

// 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.state.err = os.ErrorString("gob: attempt to decode into a non-pointer")
		return dec.state.err
	}
	return dec.DecodeValue(value)
}

// 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.state.err = nil
	for {
		// Read a count.
		var nbytes uint64
		nbytes, dec.state.err = decodeUintReader(dec.r, dec.countBuf[0:])
		if dec.state.err != nil {
			break
		}
		// Allocate the buffer.
		if nbytes > uint64(len(dec.buf)) {
			dec.buf = make([]byte, nbytes+1000)
		}
		dec.state.b = bytes.NewBuffer(dec.buf[0:nbytes])

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

		// Receive a type id.
		id := typeId(decodeInt(dec.state))
		if dec.state.err != nil {
			break
		}

		// 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.state.err != nil {
				break
			}
			continue
		}

		// No, it's a value.
		// 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.state.err = errBadType
			break
		}
		dec.state.err = dec.decode(id, value)
		break
	}
	return dec.state.err
}