blob: a3294ac50ba2026ee345fd8823be6967e96cc01b [file] [log] [blame]
Rob Pikeb948c432009-06-29 15:15:07 -07001// Copyright 2009 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package gob
6
Rob Pikeb1e64582009-07-01 23:04:27 -07007// TODO(rsc): When garbage collector changes, revisit
8// the allocations in this file that use unsafe.Pointer.
9
Rob Pikeb948c432009-06-29 15:15:07 -070010import (
Rob Pikee76a3352009-07-15 16:10:17 -070011 "bytes";
Rob Pikeb948c432009-06-29 15:15:07 -070012 "io";
Rob Pikeb96894332009-06-30 17:59:41 -070013 "math";
Rob Pikeb948c432009-06-29 15:15:07 -070014 "os";
Rob Pikec701af82009-07-01 18:25:13 -070015 "reflect";
Russ Cox33649bd2009-12-07 15:51:58 -080016 "runtime";
Rob Pike79b2cf92009-06-30 16:20:31 -070017 "unsafe";
Rob Pikeb948c432009-06-29 15:15:07 -070018)
19
Rob Pikebe2cf952009-07-16 23:01:10 -070020var (
Russ Coxc2ec9582009-10-06 19:41:51 -070021 errBadUint = os.ErrorString("gob: encoded unsigned integer out of range");
22 errBadType = os.ErrorString("gob: unknown type id or corrupted data");
23 errRange = os.ErrorString("gob: internal error: field numbers out of bounds");
24 errNotStruct = os.ErrorString("gob: TODO: can only handle structs");
Rob Pikebe2cf952009-07-16 23:01:10 -070025)
26
Rob Pike79b2cf92009-06-30 16:20:31 -070027// The global execution state of an instance of the decoder.
Rob Pikee76a3352009-07-15 16:10:17 -070028type decodeState struct {
Russ Coxc2ec9582009-10-06 19:41:51 -070029 b *bytes.Buffer;
30 err os.Error;
Rob Pikec701af82009-07-01 18:25:13 -070031 fieldnum int; // the last field number read.
Russ Coxc2ec9582009-10-06 19:41:51 -070032 buf []byte;
Rob Pikeb85147c2009-07-28 17:20:19 -070033}
34
35func newDecodeState(b *bytes.Buffer) *decodeState {
36 d := new(decodeState);
37 d.b = b;
38 d.buf = make([]byte, uint64Size);
39 return d;
Rob Pike79b2cf92009-06-30 16:20:31 -070040}
41
Rob Pike483e4fc2009-07-28 12:59:39 -070042func overflow(name string) os.ErrorString {
Robert Griesemer40621d52009-11-09 12:07:39 -080043 return os.ErrorString(`value for "` + name + `" out of range`)
Rob Pike483e4fc2009-07-28 12:59:39 -070044}
45
Rob Pikee76a3352009-07-15 16:10:17 -070046// decodeUintReader reads an encoded unsigned integer from an io.Reader.
47// Used only by the Decoder to read the message length.
Rob Pikeb85147c2009-07-28 17:20:19 -070048func decodeUintReader(r io.Reader, buf []byte) (x uint64, err os.Error) {
Russ Coxca6a0fe2009-09-15 09:41:59 -070049 _, err = r.Read(buf[0:1]);
Rob Pikeb85147c2009-07-28 17:20:19 -070050 if err != nil {
Robert Griesemer40621d52009-11-09 12:07:39 -080051 return
Rob Pikee76a3352009-07-15 16:10:17 -070052 }
Rob Pikeb85147c2009-07-28 17:20:19 -070053 b := buf[0];
54 if b <= 0x7f {
Robert Griesemer40621d52009-11-09 12:07:39 -080055 return uint64(b), nil
Rob Pikeb85147c2009-07-28 17:20:19 -070056 }
57 nb := -int(int8(b));
58 if nb > uint64Size {
59 err = errBadUint;
60 return;
61 }
62 var n int;
63 n, err = io.ReadFull(r, buf[0:nb]);
64 if err != nil {
65 if err == os.EOF {
Robert Griesemer40621d52009-11-09 12:07:39 -080066 err = io.ErrUnexpectedEOF
Rob Pikeb85147c2009-07-28 17:20:19 -070067 }
Russ Coxc2ec9582009-10-06 19:41:51 -070068 return;
Rob Pikeb85147c2009-07-28 17:20:19 -070069 }
70 // Could check that the high byte is zero but it's not worth it.
71 for i := 0; i < n; i++ {
72 x <<= 8;
73 x |= uint64(buf[i]);
74 }
Russ Coxc2ec9582009-10-06 19:41:51 -070075 return;
Rob Pikee76a3352009-07-15 16:10:17 -070076}
77
78// decodeUint reads an encoded unsigned integer from state.r.
Rob Pike79b2cf92009-06-30 16:20:31 -070079// Sets state.err. If state.err is already non-nil, it does nothing.
Rob Pike483e4fc2009-07-28 12:59:39 -070080// Does not check for overflow.
Rob Pikee76a3352009-07-15 16:10:17 -070081func decodeUint(state *decodeState) (x uint64) {
Rob Pike79b2cf92009-06-30 16:20:31 -070082 if state.err != nil {
Robert Griesemer40621d52009-11-09 12:07:39 -080083 return
Rob Pike79b2cf92009-06-30 16:20:31 -070084 }
Rob Pikeb85147c2009-07-28 17:20:19 -070085 var b uint8;
86 b, state.err = state.b.ReadByte();
87 if b <= 0x7f { // includes state.err != nil
Robert Griesemer40621d52009-11-09 12:07:39 -080088 return uint64(b)
Rob Pikeb85147c2009-07-28 17:20:19 -070089 }
90 nb := -int(int8(b));
91 if nb > uint64Size {
92 state.err = errBadUint;
93 return;
94 }
95 var n int;
96 n, state.err = state.b.Read(state.buf[0:nb]);
97 // Don't need to check error; it's safe to loop regardless.
98 // Could check that the high byte is zero but it's not worth it.
99 for i := 0; i < n; i++ {
100 x <<= 8;
101 x |= uint64(state.buf[i]);
Rob Pikeb948c432009-06-29 15:15:07 -0700102 }
Rob Pike79b2cf92009-06-30 16:20:31 -0700103 return x;
Rob Pikeb948c432009-06-29 15:15:07 -0700104}
105
Rob Pikee76a3352009-07-15 16:10:17 -0700106// decodeInt reads an encoded signed integer from state.r.
Rob Pike79b2cf92009-06-30 16:20:31 -0700107// Sets state.err. If state.err is already non-nil, it does nothing.
Rob Pike483e4fc2009-07-28 12:59:39 -0700108// Does not check for overflow.
Rob Pikee76a3352009-07-15 16:10:17 -0700109func decodeInt(state *decodeState) int64 {
110 x := decodeUint(state);
Rob Pike79b2cf92009-06-30 16:20:31 -0700111 if state.err != nil {
Robert Griesemer40621d52009-11-09 12:07:39 -0800112 return 0
Rob Pikeb948c432009-06-29 15:15:07 -0700113 }
Russ Coxc2ec9582009-10-06 19:41:51 -0700114 if x&1 != 0 {
Robert Griesemerbaba2922009-11-09 21:13:17 -0800115 return ^int64(x >> 1)
Rob Pikeb948c432009-06-29 15:15:07 -0700116 }
Robert Griesemerbaba2922009-11-09 21:13:17 -0800117 return int64(x >> 1);
Rob Pikeb948c432009-06-29 15:15:07 -0700118}
Rob Pikeb96894332009-06-30 17:59:41 -0700119
Russ Coxc2ec9582009-10-06 19:41:51 -0700120type decOp func(i *decInstr, state *decodeState, p unsafe.Pointer)
Rob Pikeb1e64582009-07-01 23:04:27 -0700121
Rob Pikeb96894332009-06-30 17:59:41 -0700122// The 'instructions' of the decoding machine
123type decInstr struct {
Rob Pikeb1e64582009-07-01 23:04:27 -0700124 op decOp;
Russ Coxc2ec9582009-10-06 19:41:51 -0700125 field int; // field number of the wire type
126 indir int; // how many pointer indirections to reach the value in the struct
Rob Pikeb96894332009-06-30 17:59:41 -0700127 offset uintptr; // offset in the structure of the field to encode
Rob Pike483e4fc2009-07-28 12:59:39 -0700128 ovfl os.ErrorString; // error message for overflow/underflow (for arrays, of the elements)
Rob Pikeb96894332009-06-30 17:59:41 -0700129}
130
131// Since the encoder writes no zeros, if we arrive at a decoder we have
132// a value to extract and store. The field number has already been read
133// (it's how we knew to call this decoder).
134// Each decoder is responsible for handling any indirections associated
135// with the data structure. If any pointer so reached is nil, allocation must
136// be done.
137
138// Walk the pointer hierarchy, allocating if we find a nil. Stop one before the end.
139func decIndirect(p unsafe.Pointer, indir int) unsafe.Pointer {
140 for ; indir > 1; indir-- {
141 if *(*unsafe.Pointer)(p) == nil {
142 // Allocation required
Robert Griesemer40621d52009-11-09 12:07:39 -0800143 *(*unsafe.Pointer)(p) = unsafe.Pointer(new(unsafe.Pointer))
Rob Pikeb96894332009-06-30 17:59:41 -0700144 }
145 p = *(*unsafe.Pointer)(p);
146 }
Russ Coxc2ec9582009-10-06 19:41:51 -0700147 return p;
Rob Pikeb96894332009-06-30 17:59:41 -0700148}
149
Rob Pike1399bad2009-07-16 17:55:16 -0700150func ignoreUint(i *decInstr, state *decodeState, p unsafe.Pointer) {
Robert Griesemer40621d52009-11-09 12:07:39 -0800151 decodeUint(state)
Rob Pike1399bad2009-07-16 17:55:16 -0700152}
153
Rob Pikee76a3352009-07-15 16:10:17 -0700154func decBool(i *decInstr, state *decodeState, p unsafe.Pointer) {
Rob Pikeb96894332009-06-30 17:59:41 -0700155 if i.indir > 0 {
Rob Pikeb96894332009-06-30 17:59:41 -0700156 if *(*unsafe.Pointer)(p) == nil {
Robert Griesemer40621d52009-11-09 12:07:39 -0800157 *(*unsafe.Pointer)(p) = unsafe.Pointer(new(bool))
Rob Pikeb96894332009-06-30 17:59:41 -0700158 }
Rob Pikec0271c42009-07-02 08:21:42 -0700159 p = *(*unsafe.Pointer)(p);
Rob Pikeb96894332009-06-30 17:59:41 -0700160 }
Rob Pikee76a3352009-07-15 16:10:17 -0700161 *(*bool)(p) = decodeInt(state) != 0;
Rob Pikeb96894332009-06-30 17:59:41 -0700162}
163
Rob Pikee76a3352009-07-15 16:10:17 -0700164func decInt8(i *decInstr, state *decodeState, p unsafe.Pointer) {
Rob Pikeb96894332009-06-30 17:59:41 -0700165 if i.indir > 0 {
Rob Pikeb96894332009-06-30 17:59:41 -0700166 if *(*unsafe.Pointer)(p) == nil {
Robert Griesemer40621d52009-11-09 12:07:39 -0800167 *(*unsafe.Pointer)(p) = unsafe.Pointer(new(int8))
Rob Pikeb96894332009-06-30 17:59:41 -0700168 }
Rob Pikec0271c42009-07-02 08:21:42 -0700169 p = *(*unsafe.Pointer)(p);
Rob Pikeb96894332009-06-30 17:59:41 -0700170 }
Rob Pike483e4fc2009-07-28 12:59:39 -0700171 v := decodeInt(state);
172 if v < math.MinInt8 || math.MaxInt8 < v {
Robert Griesemer40621d52009-11-09 12:07:39 -0800173 state.err = i.ovfl
Rob Pike483e4fc2009-07-28 12:59:39 -0700174 } else {
Robert Griesemer40621d52009-11-09 12:07:39 -0800175 *(*int8)(p) = int8(v)
Rob Pike483e4fc2009-07-28 12:59:39 -0700176 }
Rob Pikeb96894332009-06-30 17:59:41 -0700177}
178
Rob Pikee76a3352009-07-15 16:10:17 -0700179func decUint8(i *decInstr, state *decodeState, p unsafe.Pointer) {
Rob Pikeb96894332009-06-30 17:59:41 -0700180 if i.indir > 0 {
Rob Pikeb96894332009-06-30 17:59:41 -0700181 if *(*unsafe.Pointer)(p) == nil {
Robert Griesemer40621d52009-11-09 12:07:39 -0800182 *(*unsafe.Pointer)(p) = unsafe.Pointer(new(uint8))
Rob Pikeb96894332009-06-30 17:59:41 -0700183 }
Rob Pikec0271c42009-07-02 08:21:42 -0700184 p = *(*unsafe.Pointer)(p);
Rob Pikeb96894332009-06-30 17:59:41 -0700185 }
Rob Pike483e4fc2009-07-28 12:59:39 -0700186 v := decodeUint(state);
187 if math.MaxUint8 < v {
Robert Griesemer40621d52009-11-09 12:07:39 -0800188 state.err = i.ovfl
Rob Pike483e4fc2009-07-28 12:59:39 -0700189 } else {
Robert Griesemer40621d52009-11-09 12:07:39 -0800190 *(*uint8)(p) = uint8(v)
Rob Pike483e4fc2009-07-28 12:59:39 -0700191 }
Rob Pikeb96894332009-06-30 17:59:41 -0700192}
193
Rob Pikee76a3352009-07-15 16:10:17 -0700194func decInt16(i *decInstr, state *decodeState, p unsafe.Pointer) {
Rob Pikeb96894332009-06-30 17:59:41 -0700195 if i.indir > 0 {
Rob Pikeb96894332009-06-30 17:59:41 -0700196 if *(*unsafe.Pointer)(p) == nil {
Robert Griesemer40621d52009-11-09 12:07:39 -0800197 *(*unsafe.Pointer)(p) = unsafe.Pointer(new(int16))
Rob Pikeb96894332009-06-30 17:59:41 -0700198 }
Rob Pikec0271c42009-07-02 08:21:42 -0700199 p = *(*unsafe.Pointer)(p);
Rob Pikeb96894332009-06-30 17:59:41 -0700200 }
Rob Pike483e4fc2009-07-28 12:59:39 -0700201 v := decodeInt(state);
202 if v < math.MinInt16 || math.MaxInt16 < v {
Robert Griesemer40621d52009-11-09 12:07:39 -0800203 state.err = i.ovfl
Rob Pike483e4fc2009-07-28 12:59:39 -0700204 } else {
Robert Griesemer40621d52009-11-09 12:07:39 -0800205 *(*int16)(p) = int16(v)
Rob Pike483e4fc2009-07-28 12:59:39 -0700206 }
Rob Pikeb96894332009-06-30 17:59:41 -0700207}
208
Rob Pikee76a3352009-07-15 16:10:17 -0700209func decUint16(i *decInstr, state *decodeState, p unsafe.Pointer) {
Rob Pikeb96894332009-06-30 17:59:41 -0700210 if i.indir > 0 {
Rob Pikeb96894332009-06-30 17:59:41 -0700211 if *(*unsafe.Pointer)(p) == nil {
Robert Griesemer40621d52009-11-09 12:07:39 -0800212 *(*unsafe.Pointer)(p) = unsafe.Pointer(new(uint16))
Rob Pikeb96894332009-06-30 17:59:41 -0700213 }
Rob Pikec0271c42009-07-02 08:21:42 -0700214 p = *(*unsafe.Pointer)(p);
Rob Pikeb96894332009-06-30 17:59:41 -0700215 }
Rob Pike483e4fc2009-07-28 12:59:39 -0700216 v := decodeUint(state);
217 if math.MaxUint16 < v {
Robert Griesemer40621d52009-11-09 12:07:39 -0800218 state.err = i.ovfl
Rob Pike483e4fc2009-07-28 12:59:39 -0700219 } else {
Robert Griesemer40621d52009-11-09 12:07:39 -0800220 *(*uint16)(p) = uint16(v)
Rob Pike483e4fc2009-07-28 12:59:39 -0700221 }
Rob Pikeb96894332009-06-30 17:59:41 -0700222}
223
Rob Pikee76a3352009-07-15 16:10:17 -0700224func decInt32(i *decInstr, state *decodeState, p unsafe.Pointer) {
Rob Pikeb96894332009-06-30 17:59:41 -0700225 if i.indir > 0 {
Rob Pikeb96894332009-06-30 17:59:41 -0700226 if *(*unsafe.Pointer)(p) == nil {
Robert Griesemer40621d52009-11-09 12:07:39 -0800227 *(*unsafe.Pointer)(p) = unsafe.Pointer(new(int32))
Rob Pikeb96894332009-06-30 17:59:41 -0700228 }
Rob Pikec0271c42009-07-02 08:21:42 -0700229 p = *(*unsafe.Pointer)(p);
Rob Pikeb96894332009-06-30 17:59:41 -0700230 }
Rob Pike483e4fc2009-07-28 12:59:39 -0700231 v := decodeInt(state);
232 if v < math.MinInt32 || math.MaxInt32 < v {
Robert Griesemer40621d52009-11-09 12:07:39 -0800233 state.err = i.ovfl
Rob Pike483e4fc2009-07-28 12:59:39 -0700234 } else {
Robert Griesemer40621d52009-11-09 12:07:39 -0800235 *(*int32)(p) = int32(v)
Rob Pike483e4fc2009-07-28 12:59:39 -0700236 }
Rob Pikeb96894332009-06-30 17:59:41 -0700237}
238
Rob Pikee76a3352009-07-15 16:10:17 -0700239func decUint32(i *decInstr, state *decodeState, p unsafe.Pointer) {
Rob Pikeb96894332009-06-30 17:59:41 -0700240 if i.indir > 0 {
Rob Pikeb96894332009-06-30 17:59:41 -0700241 if *(*unsafe.Pointer)(p) == nil {
Robert Griesemer40621d52009-11-09 12:07:39 -0800242 *(*unsafe.Pointer)(p) = unsafe.Pointer(new(uint32))
Rob Pikeb96894332009-06-30 17:59:41 -0700243 }
Rob Pikec0271c42009-07-02 08:21:42 -0700244 p = *(*unsafe.Pointer)(p);
Rob Pikeb96894332009-06-30 17:59:41 -0700245 }
Rob Pike483e4fc2009-07-28 12:59:39 -0700246 v := decodeUint(state);
247 if math.MaxUint32 < v {
Robert Griesemer40621d52009-11-09 12:07:39 -0800248 state.err = i.ovfl
Rob Pike483e4fc2009-07-28 12:59:39 -0700249 } else {
Robert Griesemer40621d52009-11-09 12:07:39 -0800250 *(*uint32)(p) = uint32(v)
Rob Pike483e4fc2009-07-28 12:59:39 -0700251 }
Rob Pikeb96894332009-06-30 17:59:41 -0700252}
253
Rob Pikee76a3352009-07-15 16:10:17 -0700254func decInt64(i *decInstr, state *decodeState, p unsafe.Pointer) {
Rob Pikeb96894332009-06-30 17:59:41 -0700255 if i.indir > 0 {
Rob Pikeb96894332009-06-30 17:59:41 -0700256 if *(*unsafe.Pointer)(p) == nil {
Robert Griesemer40621d52009-11-09 12:07:39 -0800257 *(*unsafe.Pointer)(p) = unsafe.Pointer(new(int64))
Rob Pikeb96894332009-06-30 17:59:41 -0700258 }
Rob Pikec0271c42009-07-02 08:21:42 -0700259 p = *(*unsafe.Pointer)(p);
Rob Pikeb96894332009-06-30 17:59:41 -0700260 }
Rob Pikee76a3352009-07-15 16:10:17 -0700261 *(*int64)(p) = int64(decodeInt(state));
Rob Pikeb96894332009-06-30 17:59:41 -0700262}
263
Rob Pikee76a3352009-07-15 16:10:17 -0700264func decUint64(i *decInstr, state *decodeState, p unsafe.Pointer) {
Rob Pikeb96894332009-06-30 17:59:41 -0700265 if i.indir > 0 {
Rob Pikeb96894332009-06-30 17:59:41 -0700266 if *(*unsafe.Pointer)(p) == nil {
Robert Griesemer40621d52009-11-09 12:07:39 -0800267 *(*unsafe.Pointer)(p) = unsafe.Pointer(new(uint64))
Rob Pikeb96894332009-06-30 17:59:41 -0700268 }
Rob Pikec0271c42009-07-02 08:21:42 -0700269 p = *(*unsafe.Pointer)(p);
Rob Pikeb96894332009-06-30 17:59:41 -0700270 }
Rob Pikee76a3352009-07-15 16:10:17 -0700271 *(*uint64)(p) = uint64(decodeUint(state));
Rob Pikeb96894332009-06-30 17:59:41 -0700272}
273
274// Floating-point numbers are transmitted as uint64s holding the bits
275// of the underlying representation. They are sent byte-reversed, with
276// the exponent end coming out first, so integer floating point numbers
277// (for example) transmit more compactly. This routine does the
278// unswizzling.
279func floatFromBits(u uint64) float64 {
280 var v uint64;
281 for i := 0; i < 8; i++ {
282 v <<= 8;
Robert Griesemerbaba2922009-11-09 21:13:17 -0800283 v |= u & 0xFF;
Rob Pikeb96894332009-06-30 17:59:41 -0700284 u >>= 8;
285 }
286 return math.Float64frombits(v);
287}
288
Rob Pikee76a3352009-07-15 16:10:17 -0700289func decFloat32(i *decInstr, state *decodeState, p unsafe.Pointer) {
Rob Pikeb96894332009-06-30 17:59:41 -0700290 if i.indir > 0 {
Rob Pikeb96894332009-06-30 17:59:41 -0700291 if *(*unsafe.Pointer)(p) == nil {
Robert Griesemer40621d52009-11-09 12:07:39 -0800292 *(*unsafe.Pointer)(p) = unsafe.Pointer(new(float32))
Rob Pikeb96894332009-06-30 17:59:41 -0700293 }
Rob Pikec0271c42009-07-02 08:21:42 -0700294 p = *(*unsafe.Pointer)(p);
Rob Pikeb96894332009-06-30 17:59:41 -0700295 }
Rob Pike483e4fc2009-07-28 12:59:39 -0700296 v := floatFromBits(decodeUint(state));
297 av := v;
298 if av < 0 {
Robert Griesemer40621d52009-11-09 12:07:39 -0800299 av = -av
Rob Pike483e4fc2009-07-28 12:59:39 -0700300 }
301 if math.MaxFloat32 < av { // underflow is OK
Robert Griesemer40621d52009-11-09 12:07:39 -0800302 state.err = i.ovfl
Rob Pike483e4fc2009-07-28 12:59:39 -0700303 } else {
Robert Griesemer40621d52009-11-09 12:07:39 -0800304 *(*float32)(p) = float32(v)
Rob Pike483e4fc2009-07-28 12:59:39 -0700305 }
Rob Pikeb96894332009-06-30 17:59:41 -0700306}
307
Rob Pikee76a3352009-07-15 16:10:17 -0700308func decFloat64(i *decInstr, state *decodeState, p unsafe.Pointer) {
Rob Pikeb96894332009-06-30 17:59:41 -0700309 if i.indir > 0 {
Rob Pikeb96894332009-06-30 17:59:41 -0700310 if *(*unsafe.Pointer)(p) == nil {
Robert Griesemer40621d52009-11-09 12:07:39 -0800311 *(*unsafe.Pointer)(p) = unsafe.Pointer(new(float64))
Rob Pikeb96894332009-06-30 17:59:41 -0700312 }
Rob Pikec0271c42009-07-02 08:21:42 -0700313 p = *(*unsafe.Pointer)(p);
Rob Pikeb96894332009-06-30 17:59:41 -0700314 }
Rob Pikee76a3352009-07-15 16:10:17 -0700315 *(*float64)(p) = floatFromBits(uint64(decodeUint(state)));
Rob Pikeb96894332009-06-30 17:59:41 -0700316}
Rob Pikec701af82009-07-01 18:25:13 -0700317
Rob Pike1ca1e1b2009-07-02 11:21:01 -0700318// uint8 arrays are encoded as an unsigned count followed by the raw bytes.
Rob Pikee76a3352009-07-15 16:10:17 -0700319func decUint8Array(i *decInstr, state *decodeState, p unsafe.Pointer) {
Rob Pike1ca1e1b2009-07-02 11:21:01 -0700320 if i.indir > 0 {
321 if *(*unsafe.Pointer)(p) == nil {
Robert Griesemer40621d52009-11-09 12:07:39 -0800322 *(*unsafe.Pointer)(p) = unsafe.Pointer(new([]uint8))
Rob Pike1ca1e1b2009-07-02 11:21:01 -0700323 }
324 p = *(*unsafe.Pointer)(p);
325 }
Rob Pikee76a3352009-07-15 16:10:17 -0700326 b := make([]uint8, decodeUint(state));
327 state.b.Read(b);
Rob Pike1ca1e1b2009-07-02 11:21:01 -0700328 *(*[]uint8)(p) = b;
329}
330
331// Strings are encoded as an unsigned count followed by the raw bytes.
Rob Pikee76a3352009-07-15 16:10:17 -0700332func decString(i *decInstr, state *decodeState, p unsafe.Pointer) {
Rob Pike1ca1e1b2009-07-02 11:21:01 -0700333 if i.indir > 0 {
334 if *(*unsafe.Pointer)(p) == nil {
Robert Griesemer40621d52009-11-09 12:07:39 -0800335 *(*unsafe.Pointer)(p) = unsafe.Pointer(new([]byte))
Rob Pike1ca1e1b2009-07-02 11:21:01 -0700336 }
337 p = *(*unsafe.Pointer)(p);
338 }
Rob Pikee76a3352009-07-15 16:10:17 -0700339 b := make([]byte, decodeUint(state));
340 state.b.Read(b);
Rob Pike1ca1e1b2009-07-02 11:21:01 -0700341 *(*string)(p) = string(b);
342}
343
Rob Pike1399bad2009-07-16 17:55:16 -0700344func ignoreUint8Array(i *decInstr, state *decodeState, p unsafe.Pointer) {
345 b := make([]byte, decodeUint(state));
346 state.b.Read(b);
347}
348
Rob Pikec701af82009-07-01 18:25:13 -0700349// Execution engine
350
351// The encoder engine is an array of instructions indexed by field number of the incoming
Rob Pike30b1b9a2009-11-16 23:32:30 -0800352// decoder. It is executed with random access according to field number.
Rob Pikec701af82009-07-01 18:25:13 -0700353type decEngine struct {
Russ Coxc2ec9582009-10-06 19:41:51 -0700354 instr []decInstr;
Rob Pike1399bad2009-07-16 17:55:16 -0700355 numInstr int; // the number of active instructions
Rob Pikec701af82009-07-01 18:25:13 -0700356}
357
Rob Pikee76a3352009-07-15 16:10:17 -0700358func decodeStruct(engine *decEngine, rtyp *reflect.StructType, b *bytes.Buffer, p uintptr, indir int) os.Error {
Rob Pikec0e0f822009-10-11 18:07:47 -0700359 if indir > 0 {
Rob Pike0c33d432009-07-02 16:43:46 -0700360 up := unsafe.Pointer(p);
Rob Pikec0e0f822009-10-11 18:07:47 -0700361 if indir > 1 {
Robert Griesemer40621d52009-11-09 12:07:39 -0800362 up = decIndirect(up, indir)
Rob Pikec0e0f822009-10-11 18:07:47 -0700363 }
Rob Pike0c33d432009-07-02 16:43:46 -0700364 if *(*unsafe.Pointer)(up) == nil {
Russ Cox33649bd2009-12-07 15:51:58 -0800365 // Allocate object.
366 *(*unsafe.Pointer)(up) = unsafe.New((*runtime.StructType)(unsafe.Pointer(rtyp)))
Rob Pike0c33d432009-07-02 16:43:46 -0700367 }
368 p = *(*uintptr)(up);
369 }
Rob Pikeb85147c2009-07-28 17:20:19 -0700370 state := newDecodeState(b);
Rob Pike77baac12009-07-02 13:43:47 -0700371 state.fieldnum = -1;
Rob Pike0c33d432009-07-02 16:43:46 -0700372 basep := p;
Rob Pike77baac12009-07-02 13:43:47 -0700373 for state.err == nil {
Rob Pikee76a3352009-07-15 16:10:17 -0700374 delta := int(decodeUint(state));
Rob Piked3a29252009-07-06 10:58:55 -0700375 if delta < 0 {
376 state.err = os.ErrorString("gob decode: corrupted data: negative delta");
Russ Coxc2ec9582009-10-06 19:41:51 -0700377 break;
Rob Piked3a29252009-07-06 10:58:55 -0700378 }
Rob Pike77baac12009-07-02 13:43:47 -0700379 if state.err != nil || delta == 0 { // struct terminator is zero delta fieldnum
Robert Griesemer40621d52009-11-09 12:07:39 -0800380 break
Rob Pike77baac12009-07-02 13:43:47 -0700381 }
382 fieldnum := state.fieldnum + delta;
383 if fieldnum >= len(engine.instr) {
Rob Pike5aa17452009-07-27 11:02:06 -0700384 state.err = errRange;
Rob Pikebe2cf952009-07-16 23:01:10 -0700385 break;
Rob Pike77baac12009-07-02 13:43:47 -0700386 }
387 instr := &engine.instr[fieldnum];
Russ Coxc2ec9582009-10-06 19:41:51 -0700388 p := unsafe.Pointer(basep + instr.offset);
Rob Pike77baac12009-07-02 13:43:47 -0700389 if instr.indir > 1 {
Robert Griesemer40621d52009-11-09 12:07:39 -0800390 p = decIndirect(p, instr.indir)
Rob Pike77baac12009-07-02 13:43:47 -0700391 }
392 instr.op(instr, state, p);
393 state.fieldnum = fieldnum;
394 }
Russ Coxc2ec9582009-10-06 19:41:51 -0700395 return state.err;
Rob Pike77baac12009-07-02 13:43:47 -0700396}
397
Rob Pikecb0a02f2009-07-17 11:38:31 -0700398func ignoreStruct(engine *decEngine, b *bytes.Buffer) os.Error {
Rob Pikeb85147c2009-07-28 17:20:19 -0700399 state := newDecodeState(b);
Rob Pikecb0a02f2009-07-17 11:38:31 -0700400 state.fieldnum = -1;
401 for state.err == nil {
402 delta := int(decodeUint(state));
403 if delta < 0 {
404 state.err = os.ErrorString("gob ignore decode: corrupted data: negative delta");
Russ Coxc2ec9582009-10-06 19:41:51 -0700405 break;
Rob Pikecb0a02f2009-07-17 11:38:31 -0700406 }
407 if state.err != nil || delta == 0 { // struct terminator is zero delta fieldnum
Robert Griesemer40621d52009-11-09 12:07:39 -0800408 break
Rob Pikecb0a02f2009-07-17 11:38:31 -0700409 }
410 fieldnum := state.fieldnum + delta;
411 if fieldnum >= len(engine.instr) {
Rob Pike5aa17452009-07-27 11:02:06 -0700412 state.err = errRange;
Rob Pikecb0a02f2009-07-17 11:38:31 -0700413 break;
414 }
415 instr := &engine.instr[fieldnum];
416 instr.op(instr, state, unsafe.Pointer(nil));
417 state.fieldnum = fieldnum;
418 }
Russ Coxc2ec9582009-10-06 19:41:51 -0700419 return state.err;
Rob Pikecb0a02f2009-07-17 11:38:31 -0700420}
421
Rob Pike483e4fc2009-07-28 12:59:39 -0700422func decodeArrayHelper(state *decodeState, p uintptr, elemOp decOp, elemWid uintptr, length, elemIndir int, ovfl os.ErrorString) os.Error {
423 instr := &decInstr{elemOp, 0, elemIndir, 0, ovfl};
Rob Pike0c33d432009-07-02 16:43:46 -0700424 for i := 0; i < length && state.err == nil; i++ {
Rob Pikec1fc4c82009-07-02 17:21:48 -0700425 up := unsafe.Pointer(p);
426 if elemIndir > 1 {
Robert Griesemer40621d52009-11-09 12:07:39 -0800427 up = decIndirect(up, elemIndir)
Rob Pikec1fc4c82009-07-02 17:21:48 -0700428 }
429 elemOp(instr, state, up);
Rob Pike0c33d432009-07-02 16:43:46 -0700430 p += uintptr(elemWid);
431 }
Russ Coxc2ec9582009-10-06 19:41:51 -0700432 return state.err;
Rob Pike0c33d432009-07-02 16:43:46 -0700433}
434
Rob Pike483e4fc2009-07-28 12:59:39 -0700435func decodeArray(atyp *reflect.ArrayType, state *decodeState, p uintptr, elemOp decOp, elemWid uintptr, length, indir, elemIndir int, ovfl os.ErrorString) os.Error {
Rob Pike265674f2009-07-02 18:02:42 -0700436 if indir > 0 {
437 up := unsafe.Pointer(p);
438 if *(*unsafe.Pointer)(up) == nil {
Russ Cox33649bd2009-12-07 15:51:58 -0800439 // Allocate object.
440 *(*unsafe.Pointer)(up) = unsafe.New(atyp)
Rob Pike265674f2009-07-02 18:02:42 -0700441 }
442 p = *(*uintptr)(up);
443 }
Rob Pikee76a3352009-07-15 16:10:17 -0700444 if n := decodeUint(state); n != uint64(length) {
Robert Griesemer40621d52009-11-09 12:07:39 -0800445 return os.ErrorString("gob: length mismatch in decodeArray")
Rob Pike265674f2009-07-02 18:02:42 -0700446 }
Rob Pike483e4fc2009-07-28 12:59:39 -0700447 return decodeArrayHelper(state, p, elemOp, elemWid, length, elemIndir, ovfl);
Rob Pike265674f2009-07-02 18:02:42 -0700448}
449
Rob Pike1399bad2009-07-16 17:55:16 -0700450func ignoreArrayHelper(state *decodeState, elemOp decOp, length int) os.Error {
Rob Pike483e4fc2009-07-28 12:59:39 -0700451 instr := &decInstr{elemOp, 0, 0, 0, os.ErrorString("no error")};
Rob Pike1399bad2009-07-16 17:55:16 -0700452 for i := 0; i < length && state.err == nil; i++ {
Robert Griesemer40621d52009-11-09 12:07:39 -0800453 elemOp(instr, state, nil)
Rob Pike1399bad2009-07-16 17:55:16 -0700454 }
Russ Coxc2ec9582009-10-06 19:41:51 -0700455 return state.err;
Rob Pike1399bad2009-07-16 17:55:16 -0700456}
457
458func ignoreArray(state *decodeState, elemOp decOp, length int) os.Error {
459 if n := decodeUint(state); n != uint64(length) {
Robert Griesemer40621d52009-11-09 12:07:39 -0800460 return os.ErrorString("gob: length mismatch in ignoreArray")
Rob Pike1399bad2009-07-16 17:55:16 -0700461 }
462 return ignoreArrayHelper(state, elemOp, length);
463}
464
Rob Pike483e4fc2009-07-28 12:59:39 -0700465func decodeSlice(atyp *reflect.SliceType, state *decodeState, p uintptr, elemOp decOp, elemWid uintptr, indir, elemIndir int, ovfl os.ErrorString) os.Error {
Russ Cox33649bd2009-12-07 15:51:58 -0800466 n := int(uintptr(decodeUint(state)));
Rob Pike265674f2009-07-02 18:02:42 -0700467 if indir > 0 {
468 up := unsafe.Pointer(p);
469 if *(*unsafe.Pointer)(up) == nil {
470 // Allocate the slice header.
Russ Cox33649bd2009-12-07 15:51:58 -0800471 *(*unsafe.Pointer)(up) = unsafe.Pointer(new([]unsafe.Pointer))
Rob Pike265674f2009-07-02 18:02:42 -0700472 }
473 p = *(*uintptr)(up);
474 }
475 // Allocate storage for the slice elements, that is, the underlying array.
Rob Pike265674f2009-07-02 18:02:42 -0700476 // Always write a header at p.
477 hdrp := (*reflect.SliceHeader)(unsafe.Pointer(p));
Russ Cox33649bd2009-12-07 15:51:58 -0800478 hdrp.Data = uintptr(unsafe.NewArray(atyp.Elem(), n));
479 hdrp.Len = n;
480 hdrp.Cap = n;
481 return decodeArrayHelper(state, hdrp.Data, elemOp, elemWid, n, elemIndir, ovfl);
Rob Pike265674f2009-07-02 18:02:42 -0700482}
483
Rob Pike1399bad2009-07-16 17:55:16 -0700484func ignoreSlice(state *decodeState, elemOp decOp) os.Error {
Robert Griesemer40621d52009-11-09 12:07:39 -0800485 return ignoreArrayHelper(state, elemOp, int(decodeUint(state)))
Rob Pike1ca1e1b2009-07-02 11:21:01 -0700486}
487
Russ Coxc2ec9582009-10-06 19:41:51 -0700488var decOpMap = map[reflect.Type]decOp{
Rob Pike483e4fc2009-07-28 12:59:39 -0700489 valueKind(false): decBool,
490 valueKind(int8(0)): decInt8,
491 valueKind(int16(0)): decInt16,
492 valueKind(int32(0)): decInt32,
493 valueKind(int64(0)): decInt64,
494 valueKind(uint8(0)): decUint8,
495 valueKind(uint16(0)): decUint16,
496 valueKind(uint32(0)): decUint32,
497 valueKind(uint64(0)): decUint64,
498 valueKind(float32(0)): decFloat32,
499 valueKind(float64(0)): decFloat64,
500 valueKind("x"): decString,
Rob Pike1399bad2009-07-16 17:55:16 -0700501}
502
Russ Coxc2ec9582009-10-06 19:41:51 -0700503var decIgnoreOpMap = map[typeId]decOp{
Rob Pike1399bad2009-07-16 17:55:16 -0700504 tBool: ignoreUint,
505 tInt: ignoreUint,
506 tUint: ignoreUint,
507 tFloat: ignoreUint,
508 tBytes: ignoreUint8Array,
509 tString: ignoreUint8Array,
510}
511
Rob Pike0ae78822009-07-07 21:05:24 -0700512// Return the decoding op for the base type under rt and
513// the indirection count to reach it.
Rob Pike30b1b9a2009-11-16 23:32:30 -0800514func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string) (decOp, int, os.Error) {
Rob Pike0ae78822009-07-07 21:05:24 -0700515 typ, indir := indirect(rt);
Russ Cox87783932009-07-07 11:04:42 -0700516 op, ok := decOpMap[reflect.Typeof(typ)];
Rob Pike1ca1e1b2009-07-02 11:21:01 -0700517 if !ok {
518 // Special cases
Russ Cox87783932009-07-07 11:04:42 -0700519 switch t := typ.(type) {
520 case *reflect.SliceType:
Rob Pike483e4fc2009-07-28 12:59:39 -0700521 name = "element of " + name;
Russ Cox87783932009-07-07 11:04:42 -0700522 if _, ok := t.Elem().(*reflect.Uint8Type); ok {
523 op = decUint8Array;
524 break;
Rob Pike1ca1e1b2009-07-02 11:21:01 -0700525 }
Rob Pikea0f742d2009-12-01 15:31:28 -0800526 var elemId typeId;
527 if tt, ok := builtinIdToType[wireId]; ok {
528 elemId = tt.(*sliceType).Elem
529 } else {
530 elemId = dec.wireType[wireId].slice.Elem
531 }
Rob Pike30b1b9a2009-11-16 23:32:30 -0800532 elemOp, elemIndir, err := dec.decOpFor(elemId, t.Elem(), name);
Rob Pikebe2cf952009-07-16 23:01:10 -0700533 if err != nil {
Robert Griesemer40621d52009-11-09 12:07:39 -0800534 return nil, 0, err
Rob Pikebe2cf952009-07-16 23:01:10 -0700535 }
Rob Pike483e4fc2009-07-28 12:59:39 -0700536 ovfl := overflow(name);
Rob Pikee76a3352009-07-15 16:10:17 -0700537 op = func(i *decInstr, state *decodeState, p unsafe.Pointer) {
Robert Griesemer40621d52009-11-09 12:07:39 -0800538 state.err = decodeSlice(t, state, uintptr(p), elemOp, t.Elem().Size(), i.indir, elemIndir, ovfl)
Russ Cox87783932009-07-07 11:04:42 -0700539 };
540
541 case *reflect.ArrayType:
Rob Pike483e4fc2009-07-28 12:59:39 -0700542 name = "element of " + name;
Rob Pike1399bad2009-07-16 17:55:16 -0700543 elemId := wireId.gobType().(*arrayType).Elem;
Rob Pike30b1b9a2009-11-16 23:32:30 -0800544 elemOp, elemIndir, err := dec.decOpFor(elemId, t.Elem(), name);
Rob Pikebe2cf952009-07-16 23:01:10 -0700545 if err != nil {
Robert Griesemer40621d52009-11-09 12:07:39 -0800546 return nil, 0, err
Rob Pikebe2cf952009-07-16 23:01:10 -0700547 }
Rob Pike483e4fc2009-07-28 12:59:39 -0700548 ovfl := overflow(name);
Rob Pikee76a3352009-07-15 16:10:17 -0700549 op = func(i *decInstr, state *decodeState, p unsafe.Pointer) {
Robert Griesemer40621d52009-11-09 12:07:39 -0800550 state.err = decodeArray(t, state, uintptr(p), elemOp, t.Elem().Size(), t.Len(), i.indir, elemIndir, ovfl)
Russ Cox87783932009-07-07 11:04:42 -0700551 };
552
553 case *reflect.StructType:
Rob Pike77baac12009-07-02 13:43:47 -0700554 // Generate a closure that calls out to the engine for the nested type.
Rob Pike30b1b9a2009-11-16 23:32:30 -0800555 enginePtr, err := dec.getDecEnginePtr(wireId, typ);
Rob Pikebe2cf952009-07-16 23:01:10 -0700556 if err != nil {
Robert Griesemer40621d52009-11-09 12:07:39 -0800557 return nil, 0, err
Rob Pikebe2cf952009-07-16 23:01:10 -0700558 }
Rob Pikee76a3352009-07-15 16:10:17 -0700559 op = func(i *decInstr, state *decodeState, p unsafe.Pointer) {
Rob Pikecb0a02f2009-07-17 11:38:31 -0700560 // indirect through enginePtr to delay evaluation for recursive structs
Robert Griesemer40621d52009-11-09 12:07:39 -0800561 state.err = decodeStruct(*enginePtr, t, state.b, uintptr(p), i.indir)
Rob Pike77baac12009-07-02 13:43:47 -0700562 };
563 }
Rob Pike1ca1e1b2009-07-02 11:21:01 -0700564 }
565 if op == nil {
Robert Griesemer40621d52009-11-09 12:07:39 -0800566 return nil, 0, os.ErrorString("gob: decode can't handle type " + rt.String())
Rob Pike1ca1e1b2009-07-02 11:21:01 -0700567 }
Russ Coxc2ec9582009-10-06 19:41:51 -0700568 return op, indir, nil;
Rob Pikec701af82009-07-01 18:25:13 -0700569}
570
Rob Pike1399bad2009-07-16 17:55:16 -0700571// Return the decoding op for a field that has no destination.
Rob Pike30b1b9a2009-11-16 23:32:30 -0800572func (dec *Decoder) decIgnoreOpFor(wireId typeId) (decOp, os.Error) {
Rob Pike1399bad2009-07-16 17:55:16 -0700573 op, ok := decIgnoreOpMap[wireId];
574 if !ok {
575 // Special cases
576 switch t := wireId.gobType().(type) {
577 case *sliceType:
578 elemId := wireId.gobType().(*sliceType).Elem;
Rob Pike30b1b9a2009-11-16 23:32:30 -0800579 elemOp, err := dec.decIgnoreOpFor(elemId);
Rob Pikebe2cf952009-07-16 23:01:10 -0700580 if err != nil {
Robert Griesemer40621d52009-11-09 12:07:39 -0800581 return nil, err
Rob Pikebe2cf952009-07-16 23:01:10 -0700582 }
Robert Griesemer368f8cb2009-11-06 14:24:38 -0800583 op = func(i *decInstr, state *decodeState, p unsafe.Pointer) {
Robert Griesemer40621d52009-11-09 12:07:39 -0800584 state.err = ignoreSlice(state, elemOp)
Robert Griesemer368f8cb2009-11-06 14:24:38 -0800585 };
Rob Pike1399bad2009-07-16 17:55:16 -0700586
587 case *arrayType:
588 elemId := wireId.gobType().(*arrayType).Elem;
Rob Pike30b1b9a2009-11-16 23:32:30 -0800589 elemOp, err := dec.decIgnoreOpFor(elemId);
Rob Pikebe2cf952009-07-16 23:01:10 -0700590 if err != nil {
Robert Griesemer40621d52009-11-09 12:07:39 -0800591 return nil, err
Rob Pikebe2cf952009-07-16 23:01:10 -0700592 }
Rob Pike1399bad2009-07-16 17:55:16 -0700593 op = func(i *decInstr, state *decodeState, p unsafe.Pointer) {
Robert Griesemer40621d52009-11-09 12:07:39 -0800594 state.err = ignoreArray(state, elemOp, t.Len)
Rob Pike1399bad2009-07-16 17:55:16 -0700595 };
596
597 case *structType:
Rob Pikecb0a02f2009-07-17 11:38:31 -0700598 // Generate a closure that calls out to the engine for the nested type.
Rob Pike30b1b9a2009-11-16 23:32:30 -0800599 enginePtr, err := dec.getIgnoreEnginePtr(wireId);
Rob Pikecb0a02f2009-07-17 11:38:31 -0700600 if err != nil {
Robert Griesemer40621d52009-11-09 12:07:39 -0800601 return nil, err
Rob Pikecb0a02f2009-07-17 11:38:31 -0700602 }
603 op = func(i *decInstr, state *decodeState, p unsafe.Pointer) {
604 // indirect through enginePtr to delay evaluation for recursive structs
Robert Griesemer40621d52009-11-09 12:07:39 -0800605 state.err = ignoreStruct(*enginePtr, state.b)
Rob Pikecb0a02f2009-07-17 11:38:31 -0700606 };
Rob Pike1399bad2009-07-16 17:55:16 -0700607 }
608 }
609 if op == nil {
Rob Pike10a349a2009-12-03 17:14:32 -0800610 return nil, os.ErrorString("ignore can't handle type " + wireId.string())
Rob Pike1399bad2009-07-16 17:55:16 -0700611 }
Rob Pikebe2cf952009-07-16 23:01:10 -0700612 return op, nil;
Rob Pike1399bad2009-07-16 17:55:16 -0700613}
614
615// Are these two gob Types compatible?
Rob Pikecb0a02f2009-07-17 11:38:31 -0700616// Answers the question for basic types, arrays, and slices.
617// Structs are considered ok; fields will be checked later.
Rob Pikea0f742d2009-12-01 15:31:28 -0800618func (dec *Decoder) compatibleType(fr reflect.Type, fw typeId) bool {
Rob Pike1399bad2009-07-16 17:55:16 -0700619 for {
620 if pt, ok := fr.(*reflect.PtrType); ok {
621 fr = pt.Elem();
622 continue;
623 }
624 break;
625 }
626 switch t := fr.(type) {
627 default:
628 // interface, map, chan, etc: cannot handle.
Robert Griesemer40621d52009-11-09 12:07:39 -0800629 return false
Rob Pike1399bad2009-07-16 17:55:16 -0700630 case *reflect.BoolType:
Robert Griesemer40621d52009-11-09 12:07:39 -0800631 return fw == tBool
Rob Pike1399bad2009-07-16 17:55:16 -0700632 case *reflect.IntType:
Robert Griesemer40621d52009-11-09 12:07:39 -0800633 return fw == tInt
Rob Pike1399bad2009-07-16 17:55:16 -0700634 case *reflect.Int8Type:
Robert Griesemer40621d52009-11-09 12:07:39 -0800635 return fw == tInt
Rob Pike1399bad2009-07-16 17:55:16 -0700636 case *reflect.Int16Type:
Robert Griesemer40621d52009-11-09 12:07:39 -0800637 return fw == tInt
Rob Pike1399bad2009-07-16 17:55:16 -0700638 case *reflect.Int32Type:
Robert Griesemer40621d52009-11-09 12:07:39 -0800639 return fw == tInt
Rob Pike1399bad2009-07-16 17:55:16 -0700640 case *reflect.Int64Type:
Robert Griesemer40621d52009-11-09 12:07:39 -0800641 return fw == tInt
Rob Pike1399bad2009-07-16 17:55:16 -0700642 case *reflect.UintType:
Robert Griesemer40621d52009-11-09 12:07:39 -0800643 return fw == tUint
Rob Pike1399bad2009-07-16 17:55:16 -0700644 case *reflect.Uint8Type:
Robert Griesemer40621d52009-11-09 12:07:39 -0800645 return fw == tUint
Rob Pike1399bad2009-07-16 17:55:16 -0700646 case *reflect.Uint16Type:
Robert Griesemer40621d52009-11-09 12:07:39 -0800647 return fw == tUint
Rob Pike1399bad2009-07-16 17:55:16 -0700648 case *reflect.Uint32Type:
Robert Griesemer40621d52009-11-09 12:07:39 -0800649 return fw == tUint
Rob Pike1399bad2009-07-16 17:55:16 -0700650 case *reflect.Uint64Type:
Robert Griesemer40621d52009-11-09 12:07:39 -0800651 return fw == tUint
Rob Pike1399bad2009-07-16 17:55:16 -0700652 case *reflect.UintptrType:
Robert Griesemer40621d52009-11-09 12:07:39 -0800653 return fw == tUint
Rob Pike1399bad2009-07-16 17:55:16 -0700654 case *reflect.FloatType:
Robert Griesemer40621d52009-11-09 12:07:39 -0800655 return fw == tFloat
Rob Pike1399bad2009-07-16 17:55:16 -0700656 case *reflect.Float32Type:
Robert Griesemer40621d52009-11-09 12:07:39 -0800657 return fw == tFloat
Rob Pike1399bad2009-07-16 17:55:16 -0700658 case *reflect.Float64Type:
Robert Griesemer40621d52009-11-09 12:07:39 -0800659 return fw == tFloat
Rob Pike1399bad2009-07-16 17:55:16 -0700660 case *reflect.StringType:
Robert Griesemer40621d52009-11-09 12:07:39 -0800661 return fw == tString
Rob Pike1399bad2009-07-16 17:55:16 -0700662 case *reflect.ArrayType:
663 aw, ok := fw.gobType().(*arrayType);
Rob Pikea0f742d2009-12-01 15:31:28 -0800664 return ok && t.Len() == aw.Len && dec.compatibleType(t.Elem(), aw.Elem);
Rob Pike1399bad2009-07-16 17:55:16 -0700665 case *reflect.SliceType:
666 // Is it an array of bytes?
667 et := t.Elem();
668 if _, ok := et.(*reflect.Uint8Type); ok {
Robert Griesemer40621d52009-11-09 12:07:39 -0800669 return fw == tBytes
Rob Pike1399bad2009-07-16 17:55:16 -0700670 }
Rob Pikea0f742d2009-12-01 15:31:28 -0800671 // Extract and compare element types.
672 var sw *sliceType;
673 if tt, ok := builtinIdToType[fw]; ok {
674 sw = tt.(*sliceType)
675 } else {
676 sw = dec.wireType[fw].slice
677 }
Rob Pikecb0a02f2009-07-17 11:38:31 -0700678 elem, _ := indirect(t.Elem());
Rob Pikea0f742d2009-12-01 15:31:28 -0800679 return sw != nil && dec.compatibleType(elem, sw.Elem);
Rob Pikecb0a02f2009-07-17 11:38:31 -0700680 case *reflect.StructType:
Robert Griesemer40621d52009-11-09 12:07:39 -0800681 return true
Rob Pike1399bad2009-07-16 17:55:16 -0700682 }
683 return true;
684}
685
Rob Pike30b1b9a2009-11-16 23:32:30 -0800686func (dec *Decoder) compileDec(remoteId typeId, rt reflect.Type) (engine *decEngine, err os.Error) {
Russ Cox87783932009-07-07 11:04:42 -0700687 srt, ok1 := rt.(*reflect.StructType);
Rob Pike30b1b9a2009-11-16 23:32:30 -0800688 var wireStruct *structType;
689 // Builtin types can come from global pool; the rest must be defined by the decoder
690 if t, ok := builtinIdToType[remoteId]; ok {
691 wireStruct = t.(*structType)
692 } else {
693 w, ok2 := dec.wireType[remoteId];
694 if !ok1 || !ok2 {
695 return nil, errNotStruct
696 }
Rob Pikea0f742d2009-12-01 15:31:28 -0800697 wireStruct = w.strct;
Rob Pikec701af82009-07-01 18:25:13 -0700698 }
Rob Pikebe2cf952009-07-16 23:01:10 -0700699 engine = new(decEngine);
Rob Pike1399bad2009-07-16 17:55:16 -0700700 engine.instr = make([]decInstr, len(wireStruct.field));
701 // Loop over the fields of the wire type.
702 for fieldnum := 0; fieldnum < len(wireStruct.field); fieldnum++ {
703 wireField := wireStruct.field[fieldnum];
704 // Find the field of the local type with the same name.
Rob Pikebe2cf952009-07-16 23:01:10 -0700705 localField, present := srt.FieldByName(wireField.name);
Rob Pike483e4fc2009-07-28 12:59:39 -0700706 ovfl := overflow(wireField.name);
Rob Pike1399bad2009-07-16 17:55:16 -0700707 // TODO(r): anonymous names
Russ Cox123ff2e2009-07-28 17:01:46 -0700708 if !present {
Rob Pike30b1b9a2009-11-16 23:32:30 -0800709 op, err := dec.decIgnoreOpFor(wireField.id);
Rob Pikebe2cf952009-07-16 23:01:10 -0700710 if err != nil {
Robert Griesemer40621d52009-11-09 12:07:39 -0800711 return nil, err
Rob Pikebe2cf952009-07-16 23:01:10 -0700712 }
Rob Pike483e4fc2009-07-28 12:59:39 -0700713 engine.instr[fieldnum] = decInstr{op, fieldnum, 0, 0, ovfl};
Rob Pike1399bad2009-07-16 17:55:16 -0700714 continue;
715 }
Rob Pikea0f742d2009-12-01 15:31:28 -0800716 if !dec.compatibleType(localField.Type, wireField.id) {
Rob Pike10a349a2009-12-03 17:14:32 -0800717 details := " (" + wireField.id.string() + " incompatible with " + localField.Type.String() + ") in type " + remoteId.Name();
Rob Pike483e4fc2009-07-28 12:59:39 -0700718 return nil, os.ErrorString("gob: wrong type for field " + wireField.name + details);
Rob Pike1399bad2009-07-16 17:55:16 -0700719 }
Rob Pike30b1b9a2009-11-16 23:32:30 -0800720 op, indir, err := dec.decOpFor(wireField.id, localField.Type, localField.Name);
Rob Pikebe2cf952009-07-16 23:01:10 -0700721 if err != nil {
Robert Griesemer40621d52009-11-09 12:07:39 -0800722 return nil, err
Rob Pikebe2cf952009-07-16 23:01:10 -0700723 }
Rob Pike483e4fc2009-07-28 12:59:39 -0700724 engine.instr[fieldnum] = decInstr{op, fieldnum, indir, uintptr(localField.Offset), ovfl};
Rob Pike1399bad2009-07-16 17:55:16 -0700725 engine.numInstr++;
Rob Pikec701af82009-07-01 18:25:13 -0700726 }
Rob Pikebe2cf952009-07-16 23:01:10 -0700727 return;
Rob Pikec701af82009-07-01 18:25:13 -0700728}
729
Rob Pike30b1b9a2009-11-16 23:32:30 -0800730func (dec *Decoder) getDecEnginePtr(remoteId typeId, rt reflect.Type) (enginePtr **decEngine, err os.Error) {
731 decoderMap, ok := dec.decoderCache[rt];
Rob Pikecb0a02f2009-07-17 11:38:31 -0700732 if !ok {
Russ Coxc2ec9582009-10-06 19:41:51 -0700733 decoderMap = make(map[typeId]**decEngine);
Rob Pike30b1b9a2009-11-16 23:32:30 -0800734 dec.decoderCache[rt] = decoderMap;
Rob Pikecb0a02f2009-07-17 11:38:31 -0700735 }
Rob Pike30b1b9a2009-11-16 23:32:30 -0800736 if enginePtr, ok = decoderMap[remoteId]; !ok {
Rob Pikecb0a02f2009-07-17 11:38:31 -0700737 // To handle recursive types, mark this engine as underway before compiling.
Rob Pike1399bad2009-07-16 17:55:16 -0700738 enginePtr = new(*decEngine);
Rob Pike30b1b9a2009-11-16 23:32:30 -0800739 decoderMap[remoteId] = enginePtr;
740 *enginePtr, err = dec.compileDec(remoteId, rt);
Rob Pikebe2cf952009-07-16 23:01:10 -0700741 if err != nil {
Rob Pike30b1b9a2009-11-16 23:32:30 -0800742 decoderMap[remoteId] = nil, false
Rob Pikecb0a02f2009-07-17 11:38:31 -0700743 }
744 }
Russ Coxc2ec9582009-10-06 19:41:51 -0700745 return;
Rob Pikecb0a02f2009-07-17 11:38:31 -0700746}
747
748// When ignoring data, in effect we compile it into this type
Russ Coxc2ec9582009-10-06 19:41:51 -0700749type emptyStruct struct{}
750
Rob Pikecb0a02f2009-07-17 11:38:31 -0700751var emptyStructType = reflect.Typeof(emptyStruct{})
752
Rob Pike30b1b9a2009-11-16 23:32:30 -0800753func (dec *Decoder) getIgnoreEnginePtr(wireId typeId) (enginePtr **decEngine, err os.Error) {
Rob Pikecb0a02f2009-07-17 11:38:31 -0700754 var ok bool;
Rob Pike30b1b9a2009-11-16 23:32:30 -0800755 if enginePtr, ok = dec.ignorerCache[wireId]; !ok {
Rob Pikecb0a02f2009-07-17 11:38:31 -0700756 // To handle recursive types, mark this engine as underway before compiling.
757 enginePtr = new(*decEngine);
Rob Pike30b1b9a2009-11-16 23:32:30 -0800758 dec.ignorerCache[wireId] = enginePtr;
759 *enginePtr, err = dec.compileDec(wireId, emptyStructType);
Rob Pikecb0a02f2009-07-17 11:38:31 -0700760 if err != nil {
Rob Pike30b1b9a2009-11-16 23:32:30 -0800761 dec.ignorerCache[wireId] = nil, false
Rob Pikebe2cf952009-07-16 23:01:10 -0700762 }
Rob Pikec701af82009-07-01 18:25:13 -0700763 }
Russ Coxc2ec9582009-10-06 19:41:51 -0700764 return;
Rob Pikec701af82009-07-01 18:25:13 -0700765}
766
Rob Pike30b1b9a2009-11-16 23:32:30 -0800767func (dec *Decoder) decode(wireId typeId, e interface{}) os.Error {
Rob Pike330ab5f2009-10-11 17:37:22 -0700768 // Dereference down to the underlying struct type.
Rob Pikec1fc4c82009-07-02 17:21:48 -0700769 rt, indir := indirect(reflect.Typeof(e));
Rob Pike330ab5f2009-10-11 17:37:22 -0700770 st, ok := rt.(*reflect.StructType);
771 if !ok {
Robert Griesemer40621d52009-11-09 12:07:39 -0800772 return os.ErrorString("gob: decode can't handle " + rt.String())
Rob Pike77baac12009-07-02 13:43:47 -0700773 }
Rob Pike30b1b9a2009-11-16 23:32:30 -0800774 enginePtr, err := dec.getDecEnginePtr(wireId, rt);
Rob Pikebe2cf952009-07-16 23:01:10 -0700775 if err != nil {
Robert Griesemer40621d52009-11-09 12:07:39 -0800776 return err
Rob Pikebe2cf952009-07-16 23:01:10 -0700777 }
778 engine := *enginePtr;
Rob Pikecb0a02f2009-07-17 11:38:31 -0700779 if engine.numInstr == 0 && st.NumField() > 0 && len(wireId.gobType().(*structType).field) > 0 {
Rob Pikeba0cf082009-07-17 14:20:33 -0700780 name := rt.Name();
Russ Coxc2ec9582009-10-06 19:41:51 -0700781 return os.ErrorString("gob: type mismatch: no fields matched compiling decoder for " + name);
Rob Pike1399bad2009-07-16 17:55:16 -0700782 }
Rob Pike30b1b9a2009-11-16 23:32:30 -0800783 return decodeStruct(engine, st, dec.state.b, uintptr(reflect.NewValue(e).Addr()), indir);
Rob Pikec701af82009-07-01 18:25:13 -0700784}
Rob Pike483e4fc2009-07-28 12:59:39 -0700785
786func init() {
787 // We assume that the size of float is sufficient to tell us whether it is
788 // equivalent to float32 or to float64. This is very unlikely to be wrong.
789 var op decOp;
790 switch unsafe.Sizeof(float(0)) {
791 case unsafe.Sizeof(float32(0)):
Robert Griesemer40621d52009-11-09 12:07:39 -0800792 op = decFloat32
Rob Pike483e4fc2009-07-28 12:59:39 -0700793 case unsafe.Sizeof(float64(0)):
Robert Griesemer40621d52009-11-09 12:07:39 -0800794 op = decFloat64
Rob Pike483e4fc2009-07-28 12:59:39 -0700795 default:
Robert Griesemer40621d52009-11-09 12:07:39 -0800796 panic("gob: unknown size of float", unsafe.Sizeof(float(0)))
Rob Pike483e4fc2009-07-28 12:59:39 -0700797 }
798 decOpMap[valueKind(float(0))] = op;
799
800 // A similar assumption about int and uint. Also assume int and uint have the same size.
801 var uop decOp;
802 switch unsafe.Sizeof(int(0)) {
803 case unsafe.Sizeof(int32(0)):
804 op = decInt32;
805 uop = decUint32;
806 case unsafe.Sizeof(int64(0)):
807 op = decInt64;
808 uop = decUint64;
809 default:
Robert Griesemer40621d52009-11-09 12:07:39 -0800810 panic("gob: unknown size of int/uint", unsafe.Sizeof(int(0)))
Rob Pike483e4fc2009-07-28 12:59:39 -0700811 }
812 decOpMap[valueKind(int(0))] = op;
813 decOpMap[valueKind(uint(0))] = uop;
814
815 // Finally uintptr
816 switch unsafe.Sizeof(uintptr(0)) {
817 case unsafe.Sizeof(uint32(0)):
Robert Griesemer40621d52009-11-09 12:07:39 -0800818 uop = decUint32
Rob Pike483e4fc2009-07-28 12:59:39 -0700819 case unsafe.Sizeof(uint64(0)):
Robert Griesemer40621d52009-11-09 12:07:39 -0800820 uop = decUint64
Rob Pike483e4fc2009-07-28 12:59:39 -0700821 default:
Robert Griesemer40621d52009-11-09 12:07:39 -0800822 panic("gob: unknown size of uintptr", unsafe.Sizeof(uintptr(0)))
Rob Pike483e4fc2009-07-28 12:59:39 -0700823 }
824 decOpMap[valueKind(uintptr(0))] = uop;
825}