blob: 4d9718d01bf69775ba4f1328ace16576898fb6cb [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
7import (
Robert Griesemera3d10452009-12-15 15:35:38 -08008 "bytes"
9 "io"
10 "math"
11 "os"
12 "reflect"
13 "unsafe"
Rob Pikeb948c432009-06-29 15:15:07 -070014)
15
Rob Pikeb85147c2009-07-28 17:20:19 -070016const uint64Size = unsafe.Sizeof(uint64(0))
17
Rob Pike79b2cf92009-06-30 16:20:31 -070018// The global execution state of an instance of the encoder.
Rob Pikec701af82009-07-01 18:25:13 -070019// Field numbers are delta encoded and always increase. The field
20// number is initialized to -1 so 0 comes out as delta(1). A delta of
21// 0 terminates the structure.
Rob Pikee76a3352009-07-15 16:10:17 -070022type encoderState struct {
Robert Griesemera3d10452009-12-15 15:35:38 -080023 b *bytes.Buffer
Rob Pikea26ab292010-06-28 14:09:47 -070024 sendZero bool // encoding an array element or map key/value pair; send zero values
Robert Griesemera3d10452009-12-15 15:35:38 -080025 fieldnum int // the last field number written.
26 buf [1 + uint64Size]byte // buffer used by the encoder; here to avoid allocation.
Rob Pike79b2cf92009-06-30 16:20:31 -070027}
28
Rob Pike5d906462010-10-22 11:17:40 -070029func newEncoderState(b *bytes.Buffer) *encoderState {
30 return &encoderState{b: b}
31}
32
Rob Pikeb85147c2009-07-28 17:20:19 -070033// Unsigned integers have a two-state encoding. If the number is less
34// than 128 (0 through 0x7F), its value is written directly.
35// Otherwise the value is written in big-endian byte order preceded
36// by the byte length, negated.
Rob Pikeb948c432009-06-29 15:15:07 -070037
Rob Pikec28fa512010-10-22 16:07:26 -070038// encodeUint writes an encoded unsigned integer to state.b.
Rob Pikee76a3352009-07-15 16:10:17 -070039func encodeUint(state *encoderState, x uint64) {
Rob Pikeb85147c2009-07-28 17:20:19 -070040 if x <= 0x7F {
Rob Pikef593b372010-10-22 15:16:34 -070041 err := state.b.WriteByte(uint8(x))
42 if err != nil {
43 error(err)
44 }
Robert Griesemera3d10452009-12-15 15:35:38 -080045 return
Rob Pikeb948c432009-06-29 15:15:07 -070046 }
Robert Griesemera3d10452009-12-15 15:35:38 -080047 var n, m int
48 m = uint64Size
Rob Pikeb85147c2009-07-28 17:20:19 -070049 for n = 1; x > 0; n++ {
Robert Griesemera3d10452009-12-15 15:35:38 -080050 state.buf[m] = uint8(x & 0xFF)
51 x >>= 8
52 m--
Rob Pikeb85147c2009-07-28 17:20:19 -070053 }
Robert Griesemera3d10452009-12-15 15:35:38 -080054 state.buf[m] = uint8(-(n - 1))
Rob Pikef593b372010-10-22 15:16:34 -070055 n, err := state.b.Write(state.buf[m : uint64Size+1])
56 if err != nil {
57 error(err)
58 }
Rob Pikeb948c432009-06-29 15:15:07 -070059}
60
Rob Pikee76a3352009-07-15 16:10:17 -070061// encodeInt writes an encoded signed integer to state.w.
Rob Pikec28fa512010-10-22 16:07:26 -070062// The low bit of the encoding says whether to bit complement the (other bits of the)
63// uint to recover the int.
Russ Coxc2ec9582009-10-06 19:41:51 -070064func encodeInt(state *encoderState, i int64) {
Robert Griesemera3d10452009-12-15 15:35:38 -080065 var x uint64
Rob Pikeb948c432009-06-29 15:15:07 -070066 if i < 0 {
Robert Griesemerbaba2922009-11-09 21:13:17 -080067 x = uint64(^i<<1) | 1
Rob Pikeb948c432009-06-29 15:15:07 -070068 } else {
Robert Griesemerbaba2922009-11-09 21:13:17 -080069 x = uint64(i << 1)
Rob Pikeb948c432009-06-29 15:15:07 -070070 }
Robert Griesemera3d10452009-12-15 15:35:38 -080071 encodeUint(state, uint64(x))
Rob Pikef6f82512009-06-30 15:37:46 -070072}
73
Rob Pikee76a3352009-07-15 16:10:17 -070074type encOp func(i *encInstr, state *encoderState, p unsafe.Pointer)
Rob Pikeb1e64582009-07-01 23:04:27 -070075
Rob Pikef6f82512009-06-30 15:37:46 -070076// The 'instructions' of the encoding machine
77type encInstr struct {
Robert Griesemera3d10452009-12-15 15:35:38 -080078 op encOp
79 field int // field number
80 indir int // how many pointer indirections to reach the value in the struct
81 offset uintptr // offset in the structure of the field to encode
Rob Pikef6f82512009-06-30 15:37:46 -070082}
83
Rob Pike0c33d432009-07-02 16:43:46 -070084// Emit a field number and update the state to record its value for delta encoding.
85// If the instruction pointer is nil, do nothing
Rob Pikee76a3352009-07-15 16:10:17 -070086func (state *encoderState) update(instr *encInstr) {
Rob Pike0c33d432009-07-02 16:43:46 -070087 if instr != nil {
Robert Griesemera3d10452009-12-15 15:35:38 -080088 encodeUint(state, uint64(instr.field-state.fieldnum))
89 state.fieldnum = instr.field
Rob Pike0c33d432009-07-02 16:43:46 -070090 }
91}
92
Rob Pike79b2cf92009-06-30 16:20:31 -070093// Each encoder is responsible for handling any indirections associated
94// with the data structure. If any pointer so reached is nil, no bytes are written.
95// If the data item is zero, no bytes are written.
96// Otherwise, the output (for a scalar) is the field number, as an encoded integer,
97// followed by the field data in its appropriate format.
98
Rob Pikeb96894332009-06-30 17:59:41 -070099func encIndirect(p unsafe.Pointer, indir int) unsafe.Pointer {
100 for ; indir > 0; indir-- {
Robert Griesemera3d10452009-12-15 15:35:38 -0800101 p = *(*unsafe.Pointer)(p)
Rob Pikef6f82512009-06-30 15:37:46 -0700102 if p == nil {
Robert Griesemer40621d52009-11-09 12:07:39 -0800103 return unsafe.Pointer(nil)
Rob Pikeb96894332009-06-30 17:59:41 -0700104 }
105 }
Robert Griesemera3d10452009-12-15 15:35:38 -0800106 return p
Rob Pikeb96894332009-06-30 17:59:41 -0700107}
108
Rob Pikee76a3352009-07-15 16:10:17 -0700109func encBool(i *encInstr, state *encoderState, p unsafe.Pointer) {
Robert Griesemera3d10452009-12-15 15:35:38 -0800110 b := *(*bool)(p)
Rob Pikea26ab292010-06-28 14:09:47 -0700111 if b || state.sendZero {
Robert Griesemera3d10452009-12-15 15:35:38 -0800112 state.update(i)
Rob Pike33311a72009-12-29 07:41:53 +1100113 if b {
114 encodeUint(state, 1)
115 } else {
116 encodeUint(state, 0)
117 }
Rob Pikef6f82512009-06-30 15:37:46 -0700118 }
119}
120
Rob Pikee76a3352009-07-15 16:10:17 -0700121func encInt(i *encInstr, state *encoderState, p unsafe.Pointer) {
Robert Griesemera3d10452009-12-15 15:35:38 -0800122 v := int64(*(*int)(p))
Rob Pikea26ab292010-06-28 14:09:47 -0700123 if v != 0 || state.sendZero {
Robert Griesemera3d10452009-12-15 15:35:38 -0800124 state.update(i)
125 encodeInt(state, v)
Rob Pikef6f82512009-06-30 15:37:46 -0700126 }
127}
128
Rob Pikee76a3352009-07-15 16:10:17 -0700129func encUint(i *encInstr, state *encoderState, p unsafe.Pointer) {
Robert Griesemera3d10452009-12-15 15:35:38 -0800130 v := uint64(*(*uint)(p))
Rob Pikea26ab292010-06-28 14:09:47 -0700131 if v != 0 || state.sendZero {
Robert Griesemera3d10452009-12-15 15:35:38 -0800132 state.update(i)
133 encodeUint(state, v)
Rob Pikef6f82512009-06-30 15:37:46 -0700134 }
135}
136
Rob Pikee76a3352009-07-15 16:10:17 -0700137func encInt8(i *encInstr, state *encoderState, p unsafe.Pointer) {
Robert Griesemera3d10452009-12-15 15:35:38 -0800138 v := int64(*(*int8)(p))
Rob Pikea26ab292010-06-28 14:09:47 -0700139 if v != 0 || state.sendZero {
Robert Griesemera3d10452009-12-15 15:35:38 -0800140 state.update(i)
141 encodeInt(state, v)
Rob Pikef6f82512009-06-30 15:37:46 -0700142 }
143}
144
Rob Pikee76a3352009-07-15 16:10:17 -0700145func encUint8(i *encInstr, state *encoderState, p unsafe.Pointer) {
Robert Griesemera3d10452009-12-15 15:35:38 -0800146 v := uint64(*(*uint8)(p))
Rob Pikea26ab292010-06-28 14:09:47 -0700147 if v != 0 || state.sendZero {
Robert Griesemera3d10452009-12-15 15:35:38 -0800148 state.update(i)
149 encodeUint(state, v)
Rob Pikef6f82512009-06-30 15:37:46 -0700150 }
151}
152
Rob Pikee76a3352009-07-15 16:10:17 -0700153func encInt16(i *encInstr, state *encoderState, p unsafe.Pointer) {
Robert Griesemera3d10452009-12-15 15:35:38 -0800154 v := int64(*(*int16)(p))
Rob Pikea26ab292010-06-28 14:09:47 -0700155 if v != 0 || state.sendZero {
Robert Griesemera3d10452009-12-15 15:35:38 -0800156 state.update(i)
157 encodeInt(state, v)
Rob Pikef6f82512009-06-30 15:37:46 -0700158 }
159}
160
Rob Pikee76a3352009-07-15 16:10:17 -0700161func encUint16(i *encInstr, state *encoderState, p unsafe.Pointer) {
Robert Griesemera3d10452009-12-15 15:35:38 -0800162 v := uint64(*(*uint16)(p))
Rob Pikea26ab292010-06-28 14:09:47 -0700163 if v != 0 || state.sendZero {
Robert Griesemera3d10452009-12-15 15:35:38 -0800164 state.update(i)
165 encodeUint(state, v)
Rob Pikef6f82512009-06-30 15:37:46 -0700166 }
167}
168
Rob Pikee76a3352009-07-15 16:10:17 -0700169func encInt32(i *encInstr, state *encoderState, p unsafe.Pointer) {
Robert Griesemera3d10452009-12-15 15:35:38 -0800170 v := int64(*(*int32)(p))
Rob Pikea26ab292010-06-28 14:09:47 -0700171 if v != 0 || state.sendZero {
Robert Griesemera3d10452009-12-15 15:35:38 -0800172 state.update(i)
173 encodeInt(state, v)
Rob Pikef6f82512009-06-30 15:37:46 -0700174 }
175}
176
Rob Pikee76a3352009-07-15 16:10:17 -0700177func encUint32(i *encInstr, state *encoderState, p unsafe.Pointer) {
Robert Griesemera3d10452009-12-15 15:35:38 -0800178 v := uint64(*(*uint32)(p))
Rob Pikea26ab292010-06-28 14:09:47 -0700179 if v != 0 || state.sendZero {
Robert Griesemera3d10452009-12-15 15:35:38 -0800180 state.update(i)
181 encodeUint(state, v)
Rob Pikef6f82512009-06-30 15:37:46 -0700182 }
183}
184
Rob Pikee76a3352009-07-15 16:10:17 -0700185func encInt64(i *encInstr, state *encoderState, p unsafe.Pointer) {
Robert Griesemera3d10452009-12-15 15:35:38 -0800186 v := *(*int64)(p)
Rob Pikea26ab292010-06-28 14:09:47 -0700187 if v != 0 || state.sendZero {
Robert Griesemera3d10452009-12-15 15:35:38 -0800188 state.update(i)
189 encodeInt(state, v)
Rob Pikef6f82512009-06-30 15:37:46 -0700190 }
191}
192
Rob Pikee76a3352009-07-15 16:10:17 -0700193func encUint64(i *encInstr, state *encoderState, p unsafe.Pointer) {
Robert Griesemera3d10452009-12-15 15:35:38 -0800194 v := *(*uint64)(p)
Rob Pikea26ab292010-06-28 14:09:47 -0700195 if v != 0 || state.sendZero {
Robert Griesemera3d10452009-12-15 15:35:38 -0800196 state.update(i)
197 encodeUint(state, v)
Rob Pikef6f82512009-06-30 15:37:46 -0700198 }
199}
200
Rob Pikee76a3352009-07-15 16:10:17 -0700201func encUintptr(i *encInstr, state *encoderState, p unsafe.Pointer) {
Robert Griesemera3d10452009-12-15 15:35:38 -0800202 v := uint64(*(*uintptr)(p))
Rob Pikea26ab292010-06-28 14:09:47 -0700203 if v != 0 || state.sendZero {
Robert Griesemera3d10452009-12-15 15:35:38 -0800204 state.update(i)
205 encodeUint(state, v)
Rob Pikeec23467e2009-07-09 14:33:43 -0700206 }
207}
208
Rob Pikef6f82512009-06-30 15:37:46 -0700209// Floating-point numbers are transmitted as uint64s holding the bits
210// of the underlying representation. They are sent byte-reversed, with
211// the exponent end coming out first, so integer floating point numbers
212// (for example) transmit more compactly. This routine does the
213// swizzling.
214func floatBits(f float64) uint64 {
Robert Griesemera3d10452009-12-15 15:35:38 -0800215 u := math.Float64bits(f)
216 var v uint64
Rob Pikef6f82512009-06-30 15:37:46 -0700217 for i := 0; i < 8; i++ {
Robert Griesemera3d10452009-12-15 15:35:38 -0800218 v <<= 8
219 v |= u & 0xFF
220 u >>= 8
Rob Pikef6f82512009-06-30 15:37:46 -0700221 }
Robert Griesemera3d10452009-12-15 15:35:38 -0800222 return v
Rob Pikef6f82512009-06-30 15:37:46 -0700223}
224
Rob Pikee76a3352009-07-15 16:10:17 -0700225func encFloat(i *encInstr, state *encoderState, p unsafe.Pointer) {
Rob Pike37a6bc82010-06-24 15:07:28 -0700226 f := *(*float)(p)
Rob Pikea26ab292010-06-28 14:09:47 -0700227 if f != 0 || state.sendZero {
Robert Griesemera3d10452009-12-15 15:35:38 -0800228 v := floatBits(float64(f))
229 state.update(i)
230 encodeUint(state, v)
Rob Pikef6f82512009-06-30 15:37:46 -0700231 }
232}
233
Rob Pikee76a3352009-07-15 16:10:17 -0700234func encFloat32(i *encInstr, state *encoderState, p unsafe.Pointer) {
Rob Pike37a6bc82010-06-24 15:07:28 -0700235 f := *(*float32)(p)
Rob Pikea26ab292010-06-28 14:09:47 -0700236 if f != 0 || state.sendZero {
Robert Griesemera3d10452009-12-15 15:35:38 -0800237 v := floatBits(float64(f))
238 state.update(i)
239 encodeUint(state, v)
Rob Pikef6f82512009-06-30 15:37:46 -0700240 }
241}
242
Rob Pikee76a3352009-07-15 16:10:17 -0700243func encFloat64(i *encInstr, state *encoderState, p unsafe.Pointer) {
Robert Griesemera3d10452009-12-15 15:35:38 -0800244 f := *(*float64)(p)
Rob Pikea26ab292010-06-28 14:09:47 -0700245 if f != 0 || state.sendZero {
Robert Griesemera3d10452009-12-15 15:35:38 -0800246 state.update(i)
247 v := floatBits(f)
248 encodeUint(state, v)
Rob Pikef6f82512009-06-30 15:37:46 -0700249 }
250}
Rob Pikec701af82009-07-01 18:25:13 -0700251
Rob Pike37a6bc82010-06-24 15:07:28 -0700252// Complex numbers are just a pair of floating-point numbers, real part first.
253func encComplex(i *encInstr, state *encoderState, p unsafe.Pointer) {
254 c := *(*complex)(p)
Rob Pikea26ab292010-06-28 14:09:47 -0700255 if c != 0+0i || state.sendZero {
Rob Pike37a6bc82010-06-24 15:07:28 -0700256 rpart := floatBits(float64(real(c)))
257 ipart := floatBits(float64(imag(c)))
258 state.update(i)
259 encodeUint(state, rpart)
260 encodeUint(state, ipart)
261 }
262}
263
264func encComplex64(i *encInstr, state *encoderState, p unsafe.Pointer) {
265 c := *(*complex64)(p)
Rob Pikea26ab292010-06-28 14:09:47 -0700266 if c != 0+0i || state.sendZero {
Rob Pike37a6bc82010-06-24 15:07:28 -0700267 rpart := floatBits(float64(real(c)))
268 ipart := floatBits(float64(imag(c)))
269 state.update(i)
270 encodeUint(state, rpart)
271 encodeUint(state, ipart)
272 }
273}
274
275func encComplex128(i *encInstr, state *encoderState, p unsafe.Pointer) {
276 c := *(*complex128)(p)
Rob Pikea26ab292010-06-28 14:09:47 -0700277 if c != 0+0i || state.sendZero {
Rob Pike37a6bc82010-06-24 15:07:28 -0700278 rpart := floatBits(real(c))
279 ipart := floatBits(imag(c))
280 state.update(i)
281 encodeUint(state, rpart)
282 encodeUint(state, ipart)
283 }
284}
285
Rob Pike1ca1e1b2009-07-02 11:21:01 -0700286// Byte arrays are encoded as an unsigned count followed by the raw bytes.
Rob Pikee76a3352009-07-15 16:10:17 -0700287func encUint8Array(i *encInstr, state *encoderState, p unsafe.Pointer) {
Robert Griesemera3d10452009-12-15 15:35:38 -0800288 b := *(*[]byte)(p)
Rob Pikea26ab292010-06-28 14:09:47 -0700289 if len(b) > 0 || state.sendZero {
Robert Griesemera3d10452009-12-15 15:35:38 -0800290 state.update(i)
291 encodeUint(state, uint64(len(b)))
292 state.b.Write(b)
Rob Pike1ca1e1b2009-07-02 11:21:01 -0700293 }
294}
295
296// Strings are encoded as an unsigned count followed by the raw bytes.
Rob Pikee76a3352009-07-15 16:10:17 -0700297func encString(i *encInstr, state *encoderState, p unsafe.Pointer) {
Robert Griesemera3d10452009-12-15 15:35:38 -0800298 s := *(*string)(p)
Rob Pikea26ab292010-06-28 14:09:47 -0700299 if len(s) > 0 || state.sendZero {
Robert Griesemera3d10452009-12-15 15:35:38 -0800300 state.update(i)
301 encodeUint(state, uint64(len(s)))
302 io.WriteString(state.b, s)
Rob Pike1ca1e1b2009-07-02 11:21:01 -0700303 }
304}
305
Rob Pikec701af82009-07-01 18:25:13 -0700306// The end of a struct is marked by a delta field number of 0.
Rob Pikee76a3352009-07-15 16:10:17 -0700307func encStructTerminator(i *encInstr, state *encoderState, p unsafe.Pointer) {
Robert Griesemer40621d52009-11-09 12:07:39 -0800308 encodeUint(state, 0)
Rob Pikec701af82009-07-01 18:25:13 -0700309}
310
311// Execution engine
312
313// The encoder engine is an array of instructions indexed by field number of the encoding
314// data, typically a struct. It is executed top to bottom, walking the struct.
315type encEngine struct {
Robert Griesemera3d10452009-12-15 15:35:38 -0800316 instr []encInstr
Rob Pikec701af82009-07-01 18:25:13 -0700317}
318
Rob Pikea26ab292010-06-28 14:09:47 -0700319const singletonField = 0
320
Rob Pikec28fa512010-10-22 16:07:26 -0700321func encodeSingle(engine *encEngine, b *bytes.Buffer, basep uintptr) {
Rob Pike5d906462010-10-22 11:17:40 -0700322 state := newEncoderState(b)
Rob Pikea26ab292010-06-28 14:09:47 -0700323 state.fieldnum = singletonField
324 // There is no surrounding struct to frame the transmission, so we must
325 // generate data even if the item is zero. To do this, set sendZero.
326 state.sendZero = true
327 instr := &engine.instr[singletonField]
328 p := unsafe.Pointer(basep) // offset will be zero
329 if instr.indir > 0 {
330 if p = encIndirect(p, instr.indir); p == nil {
Rob Pikec28fa512010-10-22 16:07:26 -0700331 return
Rob Pikea26ab292010-06-28 14:09:47 -0700332 }
333 }
334 instr.op(instr, state, p)
Rob Pikea26ab292010-06-28 14:09:47 -0700335}
336
Rob Pikec28fa512010-10-22 16:07:26 -0700337func encodeStruct(engine *encEngine, b *bytes.Buffer, basep uintptr) {
Rob Pike5d906462010-10-22 11:17:40 -0700338 state := newEncoderState(b)
Robert Griesemera3d10452009-12-15 15:35:38 -0800339 state.fieldnum = -1
Rob Pike77baac12009-07-02 13:43:47 -0700340 for i := 0; i < len(engine.instr); i++ {
Robert Griesemera3d10452009-12-15 15:35:38 -0800341 instr := &engine.instr[i]
342 p := unsafe.Pointer(basep + instr.offset)
Rob Pike77baac12009-07-02 13:43:47 -0700343 if instr.indir > 0 {
344 if p = encIndirect(p, instr.indir); p == nil {
Robert Griesemer40621d52009-11-09 12:07:39 -0800345 continue
Rob Pike77baac12009-07-02 13:43:47 -0700346 }
347 }
Robert Griesemera3d10452009-12-15 15:35:38 -0800348 instr.op(instr, state, p)
Rob Pike77baac12009-07-02 13:43:47 -0700349 }
Rob Pike77baac12009-07-02 13:43:47 -0700350}
351
Rob Pikef593b372010-10-22 15:16:34 -0700352func encodeArray(b *bytes.Buffer, p uintptr, op encOp, elemWid uintptr, elemIndir int, length int) {
Rob Pike5d906462010-10-22 11:17:40 -0700353 state := newEncoderState(b)
Robert Griesemera3d10452009-12-15 15:35:38 -0800354 state.fieldnum = -1
Rob Pikea26ab292010-06-28 14:09:47 -0700355 state.sendZero = true
Robert Griesemera3d10452009-12-15 15:35:38 -0800356 encodeUint(state, uint64(length))
Rob Pikef593b372010-10-22 15:16:34 -0700357 for i := 0; i < length; i++ {
Robert Griesemera3d10452009-12-15 15:35:38 -0800358 elemp := p
359 up := unsafe.Pointer(elemp)
Rob Pikec1fc4c82009-07-02 17:21:48 -0700360 if elemIndir > 0 {
361 if up = encIndirect(up, elemIndir); up == nil {
Rob Pikef593b372010-10-22 15:16:34 -0700362 errorf("gob: encodeArray: nil element")
Rob Pikec1fc4c82009-07-02 17:21:48 -0700363 }
Robert Griesemera3d10452009-12-15 15:35:38 -0800364 elemp = uintptr(up)
Rob Pikec1fc4c82009-07-02 17:21:48 -0700365 }
Robert Griesemera3d10452009-12-15 15:35:38 -0800366 op(nil, state, unsafe.Pointer(elemp))
367 p += uintptr(elemWid)
Rob Pike0c33d432009-07-02 16:43:46 -0700368 }
Rob Pike0c33d432009-07-02 16:43:46 -0700369}
370
Rob Pike7861da72010-05-05 16:46:39 -0700371func encodeReflectValue(state *encoderState, v reflect.Value, op encOp, indir int) {
372 for i := 0; i < indir && v != nil; i++ {
373 v = reflect.Indirect(v)
374 }
375 if v == nil {
Rob Pikef593b372010-10-22 15:16:34 -0700376 errorf("gob: encodeReflectValue: nil element")
Rob Pike7861da72010-05-05 16:46:39 -0700377 }
378 op(nil, state, unsafe.Pointer(v.Addr()))
379}
380
Rob Pikef593b372010-10-22 15:16:34 -0700381func encodeMap(b *bytes.Buffer, mv *reflect.MapValue, keyOp, elemOp encOp, keyIndir, elemIndir int) {
Rob Pike5d906462010-10-22 11:17:40 -0700382 state := newEncoderState(b)
Rob Pike7861da72010-05-05 16:46:39 -0700383 state.fieldnum = -1
Rob Pikea26ab292010-06-28 14:09:47 -0700384 state.sendZero = true
Rob Pike7861da72010-05-05 16:46:39 -0700385 keys := mv.Keys()
386 encodeUint(state, uint64(len(keys)))
387 for _, key := range keys {
Rob Pike7861da72010-05-05 16:46:39 -0700388 encodeReflectValue(state, key, keyOp, keyIndir)
389 encodeReflectValue(state, mv.Elem(key), elemOp, elemIndir)
390 }
Rob Pike7861da72010-05-05 16:46:39 -0700391}
392
Rob Pike5d906462010-10-22 11:17:40 -0700393// To send an interface, we send a string identifying the concrete type, followed
394// by the type identifier (which might require defining that type right now), followed
395// by the concrete value. A nil value gets sent as the empty string for the name,
396// followed by no value.
Rob Pikef593b372010-10-22 15:16:34 -0700397func (enc *Encoder) encodeInterface(b *bytes.Buffer, iv *reflect.InterfaceValue) {
Rob Pike5d906462010-10-22 11:17:40 -0700398 state := newEncoderState(b)
399 state.fieldnum = -1
400 state.sendZero = true
401 if iv.IsNil() {
402 encodeUint(state, 0)
Rob Pikef593b372010-10-22 15:16:34 -0700403 return
Rob Pike5d906462010-10-22 11:17:40 -0700404 }
405
406 typ := iv.Elem().Type()
407 name, ok := concreteTypeToName[typ]
408 if !ok {
Rob Pikef593b372010-10-22 15:16:34 -0700409 errorf("gob: type not registered for interface: %s", typ)
Rob Pike5d906462010-10-22 11:17:40 -0700410 }
411 // Send the name.
412 encodeUint(state, uint64(len(name)))
Rob Pikef593b372010-10-22 15:16:34 -0700413 _, err := io.WriteString(state.b, name)
414 if err != nil {
415 error(err)
Rob Pike5d906462010-10-22 11:17:40 -0700416 }
417 // Send (and maybe first define) the type id.
418 enc.sendTypeDescriptor(typ)
Rob Pike5d906462010-10-22 11:17:40 -0700419 // Send the value.
Rob Pikef593b372010-10-22 15:16:34 -0700420 err = enc.encode(state.b, iv.Elem())
421 if err != nil {
422 error(err)
423 }
Rob Pike5d906462010-10-22 11:17:40 -0700424}
425
Russ Coxfc090a32010-06-21 13:19:29 -0700426var encOpMap = []encOp{
Rob Pike37a6bc82010-06-24 15:07:28 -0700427 reflect.Bool: encBool,
428 reflect.Int: encInt,
429 reflect.Int8: encInt8,
430 reflect.Int16: encInt16,
431 reflect.Int32: encInt32,
432 reflect.Int64: encInt64,
433 reflect.Uint: encUint,
434 reflect.Uint8: encUint8,
435 reflect.Uint16: encUint16,
436 reflect.Uint32: encUint32,
437 reflect.Uint64: encUint64,
438 reflect.Uintptr: encUintptr,
439 reflect.Float: encFloat,
440 reflect.Float32: encFloat32,
441 reflect.Float64: encFloat64,
442 reflect.Complex: encComplex,
443 reflect.Complex64: encComplex64,
444 reflect.Complex128: encComplex128,
445 reflect.String: encString,
Rob Pike1ca1e1b2009-07-02 11:21:01 -0700446}
447
Rob Pike0ae78822009-07-07 21:05:24 -0700448// Return the encoding op for the base type under rt and
449// the indirection count to reach it.
Rob Pikec28fa512010-10-22 16:07:26 -0700450func (enc *Encoder) encOpFor(rt reflect.Type) (encOp, int) {
Robert Griesemera3d10452009-12-15 15:35:38 -0800451 typ, indir := indirect(rt)
Russ Coxfc090a32010-06-21 13:19:29 -0700452 var op encOp
453 k := typ.Kind()
454 if int(k) < len(encOpMap) {
455 op = encOpMap[k]
456 }
457 if op == nil {
Rob Pike1ca1e1b2009-07-02 11:21:01 -0700458 // Special cases
Russ Cox87783932009-07-07 11:04:42 -0700459 switch t := typ.(type) {
460 case *reflect.SliceType:
Russ Cox45bdf032010-06-20 12:16:25 -0700461 if t.Elem().Kind() == reflect.Uint8 {
Robert Griesemera3d10452009-12-15 15:35:38 -0800462 op = encUint8Array
463 break
Rob Pike1ca1e1b2009-07-02 11:21:01 -0700464 }
Russ Cox87783932009-07-07 11:04:42 -0700465 // Slices have a header; we decode it to find the underlying array.
Rob Pikec28fa512010-10-22 16:07:26 -0700466 elemOp, indir := enc.encOpFor(t.Elem())
Rob Pikee76a3352009-07-15 16:10:17 -0700467 op = func(i *encInstr, state *encoderState, p unsafe.Pointer) {
Robert Griesemera3d10452009-12-15 15:35:38 -0800468 slice := (*reflect.SliceHeader)(p)
Russ Cox87783932009-07-07 11:04:42 -0700469 if slice.Len == 0 {
Robert Griesemer40621d52009-11-09 12:07:39 -0800470 return
Russ Cox87783932009-07-07 11:04:42 -0700471 }
Robert Griesemera3d10452009-12-15 15:35:38 -0800472 state.update(i)
Rob Pikef593b372010-10-22 15:16:34 -0700473 encodeArray(state.b, slice.Data, elemOp, t.Elem().Size(), indir, int(slice.Len))
Robert Griesemera3d10452009-12-15 15:35:38 -0800474 }
Russ Cox87783932009-07-07 11:04:42 -0700475 case *reflect.ArrayType:
476 // True arrays have size in the type.
Rob Pikec28fa512010-10-22 16:07:26 -0700477 elemOp, indir := enc.encOpFor(t.Elem())
Rob Pikee76a3352009-07-15 16:10:17 -0700478 op = func(i *encInstr, state *encoderState, p unsafe.Pointer) {
Robert Griesemera3d10452009-12-15 15:35:38 -0800479 state.update(i)
Rob Pikef593b372010-10-22 15:16:34 -0700480 encodeArray(state.b, uintptr(p), elemOp, t.Elem().Size(), indir, t.Len())
Rob Pike7861da72010-05-05 16:46:39 -0700481 }
482 case *reflect.MapType:
Rob Pikec28fa512010-10-22 16:07:26 -0700483 keyOp, keyIndir := enc.encOpFor(t.Key())
484 elemOp, elemIndir := enc.encOpFor(t.Elem())
Rob Pike7861da72010-05-05 16:46:39 -0700485 op = func(i *encInstr, state *encoderState, p unsafe.Pointer) {
Rob Pikea26ab292010-06-28 14:09:47 -0700486 // Maps cannot be accessed by moving addresses around the way
487 // that slices etc. can. We must recover a full reflection value for
488 // the iteration.
489 v := reflect.NewValue(unsafe.Unreflect(t, unsafe.Pointer((p))))
490 mv := reflect.Indirect(v).(*reflect.MapValue)
491 if mv.Len() == 0 {
492 return
493 }
Rob Pike7861da72010-05-05 16:46:39 -0700494 state.update(i)
Rob Pikef593b372010-10-22 15:16:34 -0700495 encodeMap(state.b, mv, keyOp, elemOp, keyIndir, elemIndir)
Robert Griesemera3d10452009-12-15 15:35:38 -0800496 }
Russ Cox87783932009-07-07 11:04:42 -0700497 case *reflect.StructType:
Rob Pike77baac12009-07-02 13:43:47 -0700498 // Generate a closure that calls out to the engine for the nested type.
Rob Pikec28fa512010-10-22 16:07:26 -0700499 enc.getEncEngine(typ)
Robert Griesemera3d10452009-12-15 15:35:38 -0800500 info := mustGetTypeInfo(typ)
Rob Pikee76a3352009-07-15 16:10:17 -0700501 op = func(i *encInstr, state *encoderState, p unsafe.Pointer) {
Robert Griesemera3d10452009-12-15 15:35:38 -0800502 state.update(i)
Rob Pikeec23467e2009-07-09 14:33:43 -0700503 // indirect through info to delay evaluation for recursive structs
Rob Pikef593b372010-10-22 15:16:34 -0700504 encodeStruct(info.encoder, state.b, uintptr(p))
Robert Griesemera3d10452009-12-15 15:35:38 -0800505 }
Rob Pike5d906462010-10-22 11:17:40 -0700506 case *reflect.InterfaceType:
507 op = func(i *encInstr, state *encoderState, p unsafe.Pointer) {
508 // Interfaces transmit the name and contents of the concrete
509 // value they contain.
510 v := reflect.NewValue(unsafe.Unreflect(t, unsafe.Pointer((p))))
511 iv := reflect.Indirect(v).(*reflect.InterfaceValue)
512 if !state.sendZero && (iv == nil || iv.IsNil()) {
513 return
514 }
515 state.update(i)
Rob Pikef593b372010-10-22 15:16:34 -0700516 enc.encodeInterface(state.b, iv)
Rob Pike5d906462010-10-22 11:17:40 -0700517 }
Rob Pike77baac12009-07-02 13:43:47 -0700518 }
Rob Pike1ca1e1b2009-07-02 11:21:01 -0700519 }
520 if op == nil {
Rob Pikec28fa512010-10-22 16:07:26 -0700521 errorf("gob enc: can't happen: encode type %s", rt.String())
Rob Pike1ca1e1b2009-07-02 11:21:01 -0700522 }
Rob Pikec28fa512010-10-22 16:07:26 -0700523 return op, indir
Rob Pikec701af82009-07-01 18:25:13 -0700524}
525
Rob Pikeec23467e2009-07-09 14:33:43 -0700526// The local Type was compiled from the actual value, so we know it's compatible.
Rob Pikec28fa512010-10-22 16:07:26 -0700527func (enc *Encoder) compileEnc(rt reflect.Type) *encEngine {
Rob Pikea26ab292010-06-28 14:09:47 -0700528 srt, isStruct := rt.(*reflect.StructType)
Robert Griesemera3d10452009-12-15 15:35:38 -0800529 engine := new(encEngine)
Rob Pikea26ab292010-06-28 14:09:47 -0700530 if isStruct {
531 engine.instr = make([]encInstr, srt.NumField()+1) // +1 for terminator
532 for fieldnum := 0; fieldnum < srt.NumField(); fieldnum++ {
533 f := srt.Field(fieldnum)
Rob Pikec28fa512010-10-22 16:07:26 -0700534 op, indir := enc.encOpFor(f.Type)
Rob Pikea26ab292010-06-28 14:09:47 -0700535 engine.instr[fieldnum] = encInstr{op, fieldnum, indir, uintptr(f.Offset)}
536 }
537 engine.instr[srt.NumField()] = encInstr{encStructTerminator, 0, 0, 0}
538 } else {
539 engine.instr = make([]encInstr, 1)
Rob Pikec28fa512010-10-22 16:07:26 -0700540 op, indir := enc.encOpFor(rt)
Rob Pikea26ab292010-06-28 14:09:47 -0700541 engine.instr[0] = encInstr{op, singletonField, indir, 0} // offset is zero
Rob Pikec701af82009-07-01 18:25:13 -0700542 }
Rob Pikec28fa512010-10-22 16:07:26 -0700543 return engine
Rob Pikec701af82009-07-01 18:25:13 -0700544}
545
Rob Pikeec23467e2009-07-09 14:33:43 -0700546// typeLock must be held (or we're in initialization and guaranteed single-threaded).
547// The reflection type must have all its indirections processed out.
Rob Pikec28fa512010-10-22 16:07:26 -0700548func (enc *Encoder) getEncEngine(rt reflect.Type) *encEngine {
549 info, err1 := getTypeInfo(rt)
550 if err1 != nil {
551 error(err1)
Rob Pike98607d02009-07-29 17:24:25 -0700552 }
Rob Pikeec23467e2009-07-09 14:33:43 -0700553 if info.encoder == nil {
554 // mark this engine as underway before compiling to handle recursive types.
Robert Griesemera3d10452009-12-15 15:35:38 -0800555 info.encoder = new(encEngine)
Rob Pikec28fa512010-10-22 16:07:26 -0700556 info.encoder = enc.compileEnc(rt)
Rob Pikec701af82009-07-01 18:25:13 -0700557 }
Rob Pikec28fa512010-10-22 16:07:26 -0700558 return info.encoder
Rob Pikec701af82009-07-01 18:25:13 -0700559}
560
Rob Pikec28fa512010-10-22 16:07:26 -0700561// Put this in a function so we can hold the lock only while compiling, not when encoding.
562func (enc *Encoder) lockAndGetEncEngine(rt reflect.Type) *encEngine {
563 typeLock.Lock()
564 defer typeLock.Unlock()
565 return enc.getEncEngine(rt)
566}
567
568func (enc *Encoder) encode(b *bytes.Buffer, value reflect.Value) (err os.Error) {
569 defer catchError(&err)
Rob Pikec701af82009-07-01 18:25:13 -0700570 // Dereference down to the underlying object.
Rob Pike12a4d842010-06-28 17:11:54 -0700571 rt, indir := indirect(value.Type())
Rob Pikec1fc4c82009-07-02 17:21:48 -0700572 for i := 0; i < indir; i++ {
Rob Pike12a4d842010-06-28 17:11:54 -0700573 value = reflect.Indirect(value)
Rob Pikec701af82009-07-01 18:25:13 -0700574 }
Rob Pikec28fa512010-10-22 16:07:26 -0700575 engine := enc.lockAndGetEncEngine(rt)
Rob Pikeda696852010-06-29 10:14:32 -0700576 if value.Type().Kind() == reflect.Struct {
Rob Pikec28fa512010-10-22 16:07:26 -0700577 encodeStruct(engine, b, value.Addr())
578 } else {
579 encodeSingle(engine, b, value.Addr())
Rob Pikea26ab292010-06-28 14:09:47 -0700580 }
Rob Pikec28fa512010-10-22 16:07:26 -0700581 return nil
Rob Pikec701af82009-07-01 18:25:13 -0700582}