1// 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 (
8	"errors"
9	"io"
10	"reflect"
11	"sync"
12)
13
14// An Encoder manages the transmission of type and data information to the
15// other side of a connection.  It is safe for concurrent use by multiple
16// goroutines.
17type Encoder struct {
18	mutex      sync.Mutex              // each item must be sent atomically
19	w          []io.Writer             // where to send the data
20	sent       map[reflect.Type]typeId // which types we've already sent
21	countState *encoderState           // stage for writing counts
22	freeList   *encoderState           // list of free encoderStates; avoids reallocation
23	byteBuf    encBuffer               // buffer for top-level encoderState
24	err        error
25}
26
27// Before we encode a message, we reserve space at the head of the
28// buffer in which to encode its length. This means we can use the
29// buffer to assemble the message without another allocation.
30const maxLength = 9 // Maximum size of an encoded length.
31var spaceForLength = make([]byte, maxLength)
32
33// NewEncoder returns a new encoder that will transmit on the [io.Writer].
34func NewEncoder(w io.Writer) *Encoder {
35	enc := new(Encoder)
36	enc.w = []io.Writer{w}
37	enc.sent = make(map[reflect.Type]typeId)
38	enc.countState = enc.newEncoderState(new(encBuffer))
39	return enc
40}
41
42// writer returns the innermost writer the encoder is using.
43func (enc *Encoder) writer() io.Writer {
44	return enc.w[len(enc.w)-1]
45}
46
47// pushWriter adds a writer to the encoder.
48func (enc *Encoder) pushWriter(w io.Writer) {
49	enc.w = append(enc.w, w)
50}
51
52// popWriter pops the innermost writer.
53func (enc *Encoder) popWriter() {
54	enc.w = enc.w[0 : len(enc.w)-1]
55}
56
57func (enc *Encoder) setError(err error) {
58	if enc.err == nil { // remember the first.
59		enc.err = err
60	}
61}
62
63// writeMessage sends the data item preceded by an unsigned count of its length.
64func (enc *Encoder) writeMessage(w io.Writer, b *encBuffer) {
65	// Space has been reserved for the length at the head of the message.
66	// This is a little dirty: we grab the slice from the bytes.Buffer and massage
67	// it by hand.
68	message := b.Bytes()
69	messageLen := len(message) - maxLength
70	// Length cannot be bigger than the decoder can handle.
71	if messageLen >= tooBig {
72		enc.setError(errors.New("gob: encoder: message too big"))
73		return
74	}
75	// Encode the length.
76	enc.countState.b.Reset()
77	enc.countState.encodeUint(uint64(messageLen))
78	// Copy the length to be a prefix of the message.
79	offset := maxLength - enc.countState.b.Len()
80	copy(message[offset:], enc.countState.b.Bytes())
81	// Write the data.
82	_, err := w.Write(message[offset:])
83	// Drain the buffer and restore the space at the front for the count of the next message.
84	b.Reset()
85	b.Write(spaceForLength)
86	if err != nil {
87		enc.setError(err)
88	}
89}
90
91// sendActualType sends the requested type, without further investigation, unless
92// it's been sent before.
93func (enc *Encoder) sendActualType(w io.Writer, state *encoderState, ut *userTypeInfo, actual reflect.Type) (sent bool) {
94	if _, alreadySent := enc.sent[actual]; alreadySent {
95		return false
96	}
97	info, err := getTypeInfo(ut)
98	if err != nil {
99		enc.setError(err)
100		return
101	}
102	// Send the pair (-id, type)
103	// Id:
104	state.encodeInt(-int64(info.id))
105	// Type:
106	enc.encode(state.b, reflect.ValueOf(info.wire), wireTypeUserInfo)
107	enc.writeMessage(w, state.b)
108	if enc.err != nil {
109		return
110	}
111
112	// Remember we've sent this type, both what the user gave us and the base type.
113	enc.sent[ut.base] = info.id
114	if ut.user != ut.base {
115		enc.sent[ut.user] = info.id
116	}
117	// Now send the inner types
118	switch st := actual; st.Kind() {
119	case reflect.Struct:
120		for i := 0; i < st.NumField(); i++ {
121			if isExported(st.Field(i).Name) {
122				enc.sendType(w, state, st.Field(i).Type)
123			}
124		}
125	case reflect.Array, reflect.Slice:
126		enc.sendType(w, state, st.Elem())
127	case reflect.Map:
128		enc.sendType(w, state, st.Key())
129		enc.sendType(w, state, st.Elem())
130	}
131	return true
132}
133
134// sendType sends the type info to the other side, if necessary.
135func (enc *Encoder) sendType(w io.Writer, state *encoderState, origt reflect.Type) (sent bool) {
136	ut := userType(origt)
137	if ut.externalEnc != 0 {
138		// The rules are different: regardless of the underlying type's representation,
139		// we need to tell the other side that the base type is a GobEncoder.
140		return enc.sendActualType(w, state, ut, ut.base)
141	}
142
143	// It's a concrete value, so drill down to the base type.
144	switch rt := ut.base; rt.Kind() {
145	default:
146		// Basic types and interfaces do not need to be described.
147		return
148	case reflect.Slice:
149		// If it's []uint8, don't send; it's considered basic.
150		if rt.Elem().Kind() == reflect.Uint8 {
151			return
152		}
153		// Otherwise we do send.
154		break
155	case reflect.Array:
156		// arrays must be sent so we know their lengths and element types.
157		break
158	case reflect.Map:
159		// maps must be sent so we know their lengths and key/value types.
160		break
161	case reflect.Struct:
162		// structs must be sent so we know their fields.
163		break
164	case reflect.Chan, reflect.Func:
165		// If we get here, it's a field of a struct; ignore it.
166		return
167	}
168
169	return enc.sendActualType(w, state, ut, ut.base)
170}
171
172// Encode transmits the data item represented by the empty interface value,
173// guaranteeing that all necessary type information has been transmitted first.
174// Passing a nil pointer to Encoder will panic, as they cannot be transmitted by gob.
175func (enc *Encoder) Encode(e any) error {
176	return enc.EncodeValue(reflect.ValueOf(e))
177}
178
179// sendTypeDescriptor makes sure the remote side knows about this type.
180// It will send a descriptor if this is the first time the type has been
181// sent.
182func (enc *Encoder) sendTypeDescriptor(w io.Writer, state *encoderState, ut *userTypeInfo) {
183	// Make sure the type is known to the other side.
184	// First, have we already sent this type?
185	rt := ut.base
186	if ut.externalEnc != 0 {
187		rt = ut.user
188	}
189	if _, alreadySent := enc.sent[rt]; !alreadySent {
190		// No, so send it.
191		sent := enc.sendType(w, state, rt)
192		if enc.err != nil {
193			return
194		}
195		// If the type info has still not been transmitted, it means we have
196		// a singleton basic type (int, []byte etc.) at top level. We don't
197		// need to send the type info but we do need to update enc.sent.
198		if !sent {
199			info, err := getTypeInfo(ut)
200			if err != nil {
201				enc.setError(err)
202				return
203			}
204			enc.sent[rt] = info.id
205		}
206	}
207}
208
209// sendTypeId sends the id, which must have already been defined.
210func (enc *Encoder) sendTypeId(state *encoderState, ut *userTypeInfo) {
211	// Identify the type of this top-level value.
212	state.encodeInt(int64(enc.sent[ut.base]))
213}
214
215// EncodeValue transmits the data item represented by the reflection value,
216// guaranteeing that all necessary type information has been transmitted first.
217// Passing a nil pointer to EncodeValue will panic, as they cannot be transmitted by gob.
218func (enc *Encoder) EncodeValue(value reflect.Value) error {
219	if value.Kind() == reflect.Invalid {
220		return errors.New("gob: cannot encode nil value")
221	}
222	if value.Kind() == reflect.Pointer && value.IsNil() {
223		panic("gob: cannot encode nil pointer of type " + value.Type().String())
224	}
225
226	// Make sure we're single-threaded through here, so multiple
227	// goroutines can share an encoder.
228	enc.mutex.Lock()
229	defer enc.mutex.Unlock()
230
231	// Remove any nested writers remaining due to previous errors.
232	enc.w = enc.w[0:1]
233
234	ut, err := validUserType(value.Type())
235	if err != nil {
236		return err
237	}
238
239	enc.err = nil
240	enc.byteBuf.Reset()
241	enc.byteBuf.Write(spaceForLength)
242	state := enc.newEncoderState(&enc.byteBuf)
243
244	enc.sendTypeDescriptor(enc.writer(), state, ut)
245	enc.sendTypeId(state, ut)
246	if enc.err != nil {
247		return enc.err
248	}
249
250	// Encode the object.
251	enc.encode(state.b, value, ut)
252	if enc.err == nil {
253		enc.writeMessage(enc.writer(), state.b)
254	}
255
256	enc.freeEncoderState(state)
257	return enc.err
258}
259