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	"encoding"
9	"errors"
10	"fmt"
11	"os"
12	"reflect"
13	"sync"
14	"sync/atomic"
15	"unicode"
16	"unicode/utf8"
17)
18
19// userTypeInfo stores the information associated with a type the user has handed
20// to the package. It's computed once and stored in a map keyed by reflection
21// type.
22type userTypeInfo struct {
23	user        reflect.Type // the type the user handed us
24	base        reflect.Type // the base type after all indirections
25	indir       int          // number of indirections to reach the base type
26	externalEnc int          // xGob, xBinary, or xText
27	externalDec int          // xGob, xBinary, or xText
28	encIndir    int8         // number of indirections to reach the receiver type; may be negative
29	decIndir    int8         // number of indirections to reach the receiver type; may be negative
30}
31
32// externalEncoding bits
33const (
34	xGob    = 1 + iota // GobEncoder or GobDecoder
35	xBinary            // encoding.BinaryMarshaler or encoding.BinaryUnmarshaler
36	xText              // encoding.TextMarshaler or encoding.TextUnmarshaler
37)
38
39var userTypeCache sync.Map // map[reflect.Type]*userTypeInfo
40
41// validUserType returns, and saves, the information associated with user-provided type rt.
42// If the user type is not valid, err will be non-nil. To be used when the error handler
43// is not set up.
44func validUserType(rt reflect.Type) (*userTypeInfo, error) {
45	if ui, ok := userTypeCache.Load(rt); ok {
46		return ui.(*userTypeInfo), nil
47	}
48
49	// Construct a new userTypeInfo and atomically add it to the userTypeCache.
50	// If we lose the race, we'll waste a little CPU and create a little garbage
51	// but return the existing value anyway.
52
53	ut := new(userTypeInfo)
54	ut.base = rt
55	ut.user = rt
56	// A type that is just a cycle of pointers (such as type T *T) cannot
57	// be represented in gobs, which need some concrete data. We use a
58	// cycle detection algorithm from Knuth, Vol 2, Section 3.1, Ex 6,
59	// pp 539-540.  As we step through indirections, run another type at
60	// half speed. If they meet up, there's a cycle.
61	slowpoke := ut.base // walks half as fast as ut.base
62	for {
63		pt := ut.base
64		if pt.Kind() != reflect.Pointer {
65			break
66		}
67		ut.base = pt.Elem()
68		if ut.base == slowpoke { // ut.base lapped slowpoke
69			// recursive pointer type.
70			return nil, errors.New("can't represent recursive pointer type " + ut.base.String())
71		}
72		if ut.indir%2 == 0 {
73			slowpoke = slowpoke.Elem()
74		}
75		ut.indir++
76	}
77
78	if ok, indir := implementsInterface(ut.user, gobEncoderInterfaceType); ok {
79		ut.externalEnc, ut.encIndir = xGob, indir
80	} else if ok, indir := implementsInterface(ut.user, binaryMarshalerInterfaceType); ok {
81		ut.externalEnc, ut.encIndir = xBinary, indir
82	}
83
84	// NOTE(rsc): Would like to allow MarshalText here, but results in incompatibility
85	// with older encodings for net.IP. See golang.org/issue/6760.
86	// } else if ok, indir := implementsInterface(ut.user, textMarshalerInterfaceType); ok {
87	// 	ut.externalEnc, ut.encIndir = xText, indir
88	// }
89
90	if ok, indir := implementsInterface(ut.user, gobDecoderInterfaceType); ok {
91		ut.externalDec, ut.decIndir = xGob, indir
92	} else if ok, indir := implementsInterface(ut.user, binaryUnmarshalerInterfaceType); ok {
93		ut.externalDec, ut.decIndir = xBinary, indir
94	}
95
96	// See note above.
97	// } else if ok, indir := implementsInterface(ut.user, textUnmarshalerInterfaceType); ok {
98	// 	ut.externalDec, ut.decIndir = xText, indir
99	// }
100
101	ui, _ := userTypeCache.LoadOrStore(rt, ut)
102	return ui.(*userTypeInfo), nil
103}
104
105var (
106	gobEncoderInterfaceType        = reflect.TypeFor[GobEncoder]()
107	gobDecoderInterfaceType        = reflect.TypeFor[GobDecoder]()
108	binaryMarshalerInterfaceType   = reflect.TypeFor[encoding.BinaryMarshaler]()
109	binaryUnmarshalerInterfaceType = reflect.TypeFor[encoding.BinaryUnmarshaler]()
110	textMarshalerInterfaceType     = reflect.TypeFor[encoding.TextMarshaler]()
111	textUnmarshalerInterfaceType   = reflect.TypeFor[encoding.TextUnmarshaler]()
112
113	wireTypeType = reflect.TypeFor[wireType]()
114)
115
116// implementsInterface reports whether the type implements the
117// gobEncoder/gobDecoder interface.
118// It also returns the number of indirections required to get to the
119// implementation.
120func implementsInterface(typ, gobEncDecType reflect.Type) (success bool, indir int8) {
121	if typ == nil {
122		return
123	}
124	rt := typ
125	// The type might be a pointer and we need to keep
126	// dereferencing to the base type until we find an implementation.
127	for {
128		if rt.Implements(gobEncDecType) {
129			return true, indir
130		}
131		if p := rt; p.Kind() == reflect.Pointer {
132			indir++
133			if indir > 100 { // insane number of indirections
134				return false, 0
135			}
136			rt = p.Elem()
137			continue
138		}
139		break
140	}
141	// No luck yet, but if this is a base type (non-pointer), the pointer might satisfy.
142	if typ.Kind() != reflect.Pointer {
143		// Not a pointer, but does the pointer work?
144		if reflect.PointerTo(typ).Implements(gobEncDecType) {
145			return true, -1
146		}
147	}
148	return false, 0
149}
150
151// userType returns, and saves, the information associated with user-provided type rt.
152// If the user type is not valid, it calls error.
153func userType(rt reflect.Type) *userTypeInfo {
154	ut, err := validUserType(rt)
155	if err != nil {
156		error_(err)
157	}
158	return ut
159}
160
161// A typeId represents a gob Type as an integer that can be passed on the wire.
162// Internally, typeIds are used as keys to a map to recover the underlying type info.
163type typeId int32
164
165var typeLock sync.Mutex // set while building a type
166const firstUserId = 64  // lowest id number granted to user
167
168type gobType interface {
169	id() typeId
170	setId(id typeId)
171	name() string
172	string() string // not public; only for debugging
173	safeString(seen map[typeId]bool) string
174}
175
176var (
177	types                = make(map[reflect.Type]gobType, 32)
178	idToTypeSlice        = make([]gobType, 1, firstUserId)
179	builtinIdToTypeSlice [firstUserId]gobType // set in init() after builtins are established
180)
181
182func idToType(id typeId) gobType {
183	if id < 0 || int(id) >= len(idToTypeSlice) {
184		return nil
185	}
186	return idToTypeSlice[id]
187}
188
189func builtinIdToType(id typeId) gobType {
190	if id < 0 || int(id) >= len(builtinIdToTypeSlice) {
191		return nil
192	}
193	return builtinIdToTypeSlice[id]
194}
195
196func setTypeId(typ gobType) {
197	// When building recursive types, someone may get there before us.
198	if typ.id() != 0 {
199		return
200	}
201	nextId := typeId(len(idToTypeSlice))
202	typ.setId(nextId)
203	idToTypeSlice = append(idToTypeSlice, typ)
204}
205
206func (t typeId) gobType() gobType {
207	if t == 0 {
208		return nil
209	}
210	return idToType(t)
211}
212
213// string returns the string representation of the type associated with the typeId.
214func (t typeId) string() string {
215	if t.gobType() == nil {
216		return "<nil>"
217	}
218	return t.gobType().string()
219}
220
221// Name returns the name of the type associated with the typeId.
222func (t typeId) name() string {
223	if t.gobType() == nil {
224		return "<nil>"
225	}
226	return t.gobType().name()
227}
228
229// CommonType holds elements of all types.
230// It is a historical artifact, kept for binary compatibility and exported
231// only for the benefit of the package's encoding of type descriptors. It is
232// not intended for direct use by clients.
233type CommonType struct {
234	Name string
235	Id   typeId
236}
237
238func (t *CommonType) id() typeId { return t.Id }
239
240func (t *CommonType) setId(id typeId) { t.Id = id }
241
242func (t *CommonType) string() string { return t.Name }
243
244func (t *CommonType) safeString(seen map[typeId]bool) string {
245	return t.Name
246}
247
248func (t *CommonType) name() string { return t.Name }
249
250// Create and check predefined types
251// The string for tBytes is "bytes" not "[]byte" to signify its specialness.
252
253var (
254	// Primordial types, needed during initialization.
255	// Always passed as pointers so the interface{} type
256	// goes through without losing its interfaceness.
257	tBool      = bootstrapType("bool", (*bool)(nil))
258	tInt       = bootstrapType("int", (*int)(nil))
259	tUint      = bootstrapType("uint", (*uint)(nil))
260	tFloat     = bootstrapType("float", (*float64)(nil))
261	tBytes     = bootstrapType("bytes", (*[]byte)(nil))
262	tString    = bootstrapType("string", (*string)(nil))
263	tComplex   = bootstrapType("complex", (*complex128)(nil))
264	tInterface = bootstrapType("interface", (*any)(nil))
265	// Reserve some Ids for compatible expansion
266	tReserved7 = bootstrapType("_reserved1", (*struct{ r7 int })(nil))
267	tReserved6 = bootstrapType("_reserved1", (*struct{ r6 int })(nil))
268	tReserved5 = bootstrapType("_reserved1", (*struct{ r5 int })(nil))
269	tReserved4 = bootstrapType("_reserved1", (*struct{ r4 int })(nil))
270	tReserved3 = bootstrapType("_reserved1", (*struct{ r3 int })(nil))
271	tReserved2 = bootstrapType("_reserved1", (*struct{ r2 int })(nil))
272	tReserved1 = bootstrapType("_reserved1", (*struct{ r1 int })(nil))
273)
274
275// Predefined because it's needed by the Decoder
276var tWireType = mustGetTypeInfo(wireTypeType).id
277var wireTypeUserInfo *userTypeInfo // userTypeInfo of wireType
278
279func init() {
280	// Some magic numbers to make sure there are no surprises.
281	checkId(16, tWireType)
282	checkId(17, mustGetTypeInfo(reflect.TypeFor[arrayType]()).id)
283	checkId(18, mustGetTypeInfo(reflect.TypeFor[CommonType]()).id)
284	checkId(19, mustGetTypeInfo(reflect.TypeFor[sliceType]()).id)
285	checkId(20, mustGetTypeInfo(reflect.TypeFor[structType]()).id)
286	checkId(21, mustGetTypeInfo(reflect.TypeFor[fieldType]()).id)
287	checkId(23, mustGetTypeInfo(reflect.TypeFor[mapType]()).id)
288
289	copy(builtinIdToTypeSlice[:], idToTypeSlice)
290
291	// Move the id space upwards to allow for growth in the predefined world
292	// without breaking existing files.
293	if nextId := len(idToTypeSlice); nextId > firstUserId {
294		panic(fmt.Sprintln("nextId too large:", nextId))
295	}
296	idToTypeSlice = idToTypeSlice[:firstUserId]
297	registerBasics()
298	wireTypeUserInfo = userType(wireTypeType)
299}
300
301// Array type
302type arrayType struct {
303	CommonType
304	Elem typeId
305	Len  int
306}
307
308func newArrayType(name string) *arrayType {
309	a := &arrayType{CommonType{Name: name}, 0, 0}
310	return a
311}
312
313func (a *arrayType) init(elem gobType, len int) {
314	// Set our type id before evaluating the element's, in case it's our own.
315	setTypeId(a)
316	a.Elem = elem.id()
317	a.Len = len
318}
319
320func (a *arrayType) safeString(seen map[typeId]bool) string {
321	if seen[a.Id] {
322		return a.Name
323	}
324	seen[a.Id] = true
325	return fmt.Sprintf("[%d]%s", a.Len, a.Elem.gobType().safeString(seen))
326}
327
328func (a *arrayType) string() string { return a.safeString(make(map[typeId]bool)) }
329
330// GobEncoder type (something that implements the GobEncoder interface)
331type gobEncoderType struct {
332	CommonType
333}
334
335func newGobEncoderType(name string) *gobEncoderType {
336	g := &gobEncoderType{CommonType{Name: name}}
337	setTypeId(g)
338	return g
339}
340
341func (g *gobEncoderType) safeString(seen map[typeId]bool) string {
342	return g.Name
343}
344
345func (g *gobEncoderType) string() string { return g.Name }
346
347// Map type
348type mapType struct {
349	CommonType
350	Key  typeId
351	Elem typeId
352}
353
354func newMapType(name string) *mapType {
355	m := &mapType{CommonType{Name: name}, 0, 0}
356	return m
357}
358
359func (m *mapType) init(key, elem gobType) {
360	// Set our type id before evaluating the element's, in case it's our own.
361	setTypeId(m)
362	m.Key = key.id()
363	m.Elem = elem.id()
364}
365
366func (m *mapType) safeString(seen map[typeId]bool) string {
367	if seen[m.Id] {
368		return m.Name
369	}
370	seen[m.Id] = true
371	key := m.Key.gobType().safeString(seen)
372	elem := m.Elem.gobType().safeString(seen)
373	return fmt.Sprintf("map[%s]%s", key, elem)
374}
375
376func (m *mapType) string() string { return m.safeString(make(map[typeId]bool)) }
377
378// Slice type
379type sliceType struct {
380	CommonType
381	Elem typeId
382}
383
384func newSliceType(name string) *sliceType {
385	s := &sliceType{CommonType{Name: name}, 0}
386	return s
387}
388
389func (s *sliceType) init(elem gobType) {
390	// Set our type id before evaluating the element's, in case it's our own.
391	setTypeId(s)
392	// See the comments about ids in newTypeObject. Only slices and
393	// structs have mutual recursion.
394	if elem.id() == 0 {
395		setTypeId(elem)
396	}
397	s.Elem = elem.id()
398}
399
400func (s *sliceType) safeString(seen map[typeId]bool) string {
401	if seen[s.Id] {
402		return s.Name
403	}
404	seen[s.Id] = true
405	return fmt.Sprintf("[]%s", s.Elem.gobType().safeString(seen))
406}
407
408func (s *sliceType) string() string { return s.safeString(make(map[typeId]bool)) }
409
410// Struct type
411type fieldType struct {
412	Name string
413	Id   typeId
414}
415
416type structType struct {
417	CommonType
418	Field []fieldType
419}
420
421func (s *structType) safeString(seen map[typeId]bool) string {
422	if s == nil {
423		return "<nil>"
424	}
425	if _, ok := seen[s.Id]; ok {
426		return s.Name
427	}
428	seen[s.Id] = true
429	str := s.Name + " = struct { "
430	for _, f := range s.Field {
431		str += fmt.Sprintf("%s %s; ", f.Name, f.Id.gobType().safeString(seen))
432	}
433	str += "}"
434	return str
435}
436
437func (s *structType) string() string { return s.safeString(make(map[typeId]bool)) }
438
439func newStructType(name string) *structType {
440	s := &structType{CommonType{Name: name}, nil}
441	// For historical reasons we set the id here rather than init.
442	// See the comment in newTypeObject for details.
443	setTypeId(s)
444	return s
445}
446
447// newTypeObject allocates a gobType for the reflection type rt.
448// Unless ut represents a GobEncoder, rt should be the base type
449// of ut.
450// This is only called from the encoding side. The decoding side
451// works through typeIds and userTypeInfos alone.
452func newTypeObject(name string, ut *userTypeInfo, rt reflect.Type) (gobType, error) {
453	// Does this type implement GobEncoder?
454	if ut.externalEnc != 0 {
455		return newGobEncoderType(name), nil
456	}
457	var err error
458	var type0, type1 gobType
459	defer func() {
460		if err != nil {
461			delete(types, rt)
462		}
463	}()
464	// Install the top-level type before the subtypes (e.g. struct before
465	// fields) so recursive types can be constructed safely.
466	switch t := rt; t.Kind() {
467	// All basic types are easy: they are predefined.
468	case reflect.Bool:
469		return tBool.gobType(), nil
470
471	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
472		return tInt.gobType(), nil
473
474	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
475		return tUint.gobType(), nil
476
477	case reflect.Float32, reflect.Float64:
478		return tFloat.gobType(), nil
479
480	case reflect.Complex64, reflect.Complex128:
481		return tComplex.gobType(), nil
482
483	case reflect.String:
484		return tString.gobType(), nil
485
486	case reflect.Interface:
487		return tInterface.gobType(), nil
488
489	case reflect.Array:
490		at := newArrayType(name)
491		types[rt] = at
492		type0, err = getBaseType("", t.Elem())
493		if err != nil {
494			return nil, err
495		}
496		// Historical aside:
497		// For arrays, maps, and slices, we set the type id after the elements
498		// are constructed. This is to retain the order of type id allocation after
499		// a fix made to handle recursive types, which changed the order in
500		// which types are built. Delaying the setting in this way preserves
501		// type ids while allowing recursive types to be described. Structs,
502		// done below, were already handling recursion correctly so they
503		// assign the top-level id before those of the field.
504		at.init(type0, t.Len())
505		return at, nil
506
507	case reflect.Map:
508		mt := newMapType(name)
509		types[rt] = mt
510		type0, err = getBaseType("", t.Key())
511		if err != nil {
512			return nil, err
513		}
514		type1, err = getBaseType("", t.Elem())
515		if err != nil {
516			return nil, err
517		}
518		mt.init(type0, type1)
519		return mt, nil
520
521	case reflect.Slice:
522		// []byte == []uint8 is a special case
523		if t.Elem().Kind() == reflect.Uint8 {
524			return tBytes.gobType(), nil
525		}
526		st := newSliceType(name)
527		types[rt] = st
528		type0, err = getBaseType(t.Elem().Name(), t.Elem())
529		if err != nil {
530			return nil, err
531		}
532		st.init(type0)
533		return st, nil
534
535	case reflect.Struct:
536		st := newStructType(name)
537		types[rt] = st
538		idToTypeSlice[st.id()] = st
539		for i := 0; i < t.NumField(); i++ {
540			f := t.Field(i)
541			if !isSent(&f) {
542				continue
543			}
544			typ := userType(f.Type).base
545			tname := typ.Name()
546			if tname == "" {
547				t := userType(f.Type).base
548				tname = t.String()
549			}
550			gt, err := getBaseType(tname, f.Type)
551			if err != nil {
552				return nil, err
553			}
554			// Some mutually recursive types can cause us to be here while
555			// still defining the element. Fix the element type id here.
556			// We could do this more neatly by setting the id at the start of
557			// building every type, but that would break binary compatibility.
558			if gt.id() == 0 {
559				setTypeId(gt)
560			}
561			st.Field = append(st.Field, fieldType{f.Name, gt.id()})
562		}
563		return st, nil
564
565	default:
566		return nil, errors.New("gob NewTypeObject can't handle type: " + rt.String())
567	}
568}
569
570// isExported reports whether this is an exported - upper case - name.
571func isExported(name string) bool {
572	rune, _ := utf8.DecodeRuneInString(name)
573	return unicode.IsUpper(rune)
574}
575
576// isSent reports whether this struct field is to be transmitted.
577// It will be transmitted only if it is exported and not a chan or func field
578// or pointer to chan or func.
579func isSent(field *reflect.StructField) bool {
580	if !isExported(field.Name) {
581		return false
582	}
583	// If the field is a chan or func or pointer thereto, don't send it.
584	// That is, treat it like an unexported field.
585	typ := field.Type
586	for typ.Kind() == reflect.Pointer {
587		typ = typ.Elem()
588	}
589	if typ.Kind() == reflect.Chan || typ.Kind() == reflect.Func {
590		return false
591	}
592
593	return true
594}
595
596// getBaseType returns the Gob type describing the given reflect.Type's base type.
597// typeLock must be held.
598func getBaseType(name string, rt reflect.Type) (gobType, error) {
599	ut := userType(rt)
600	return getType(name, ut, ut.base)
601}
602
603// getType returns the Gob type describing the given reflect.Type.
604// Should be called only when handling GobEncoders/Decoders,
605// which may be pointers. All other types are handled through the
606// base type, never a pointer.
607// typeLock must be held.
608func getType(name string, ut *userTypeInfo, rt reflect.Type) (gobType, error) {
609	typ, present := types[rt]
610	if present {
611		return typ, nil
612	}
613	typ, err := newTypeObject(name, ut, rt)
614	if err == nil {
615		types[rt] = typ
616	}
617	return typ, err
618}
619
620func checkId(want, got typeId) {
621	if want != got {
622		fmt.Fprintf(os.Stderr, "checkId: %d should be %d\n", int(got), int(want))
623		panic("bootstrap type wrong id: " + got.name() + " " + got.string() + " not " + want.string())
624	}
625}
626
627// used for building the basic types; called only from init().  the incoming
628// interface always refers to a pointer.
629func bootstrapType(name string, e any) typeId {
630	rt := reflect.TypeOf(e).Elem()
631	_, present := types[rt]
632	if present {
633		panic("bootstrap type already present: " + name + ", " + rt.String())
634	}
635	typ := &CommonType{Name: name}
636	types[rt] = typ
637	setTypeId(typ)
638	return typ.id()
639}
640
641// Representation of the information we send and receive about this type.
642// Each value we send is preceded by its type definition: an encoded int.
643// However, the very first time we send the value, we first send the pair
644// (-id, wireType).
645// For bootstrapping purposes, we assume that the recipient knows how
646// to decode a wireType; it is exactly the wireType struct here, interpreted
647// using the gob rules for sending a structure, except that we assume the
648// ids for wireType and structType etc. are known. The relevant pieces
649// are built in encode.go's init() function.
650// To maintain binary compatibility, if you extend this type, always put
651// the new fields last.
652type wireType struct {
653	ArrayT           *arrayType
654	SliceT           *sliceType
655	StructT          *structType
656	MapT             *mapType
657	GobEncoderT      *gobEncoderType
658	BinaryMarshalerT *gobEncoderType
659	TextMarshalerT   *gobEncoderType
660}
661
662func (w *wireType) string() string {
663	const unknown = "unknown type"
664	if w == nil {
665		return unknown
666	}
667	switch {
668	case w.ArrayT != nil:
669		return w.ArrayT.Name
670	case w.SliceT != nil:
671		return w.SliceT.Name
672	case w.StructT != nil:
673		return w.StructT.Name
674	case w.MapT != nil:
675		return w.MapT.Name
676	case w.GobEncoderT != nil:
677		return w.GobEncoderT.Name
678	case w.BinaryMarshalerT != nil:
679		return w.BinaryMarshalerT.Name
680	case w.TextMarshalerT != nil:
681		return w.TextMarshalerT.Name
682	}
683	return unknown
684}
685
686type typeInfo struct {
687	id      typeId
688	encInit sync.Mutex // protects creation of encoder
689	encoder atomic.Pointer[encEngine]
690	wire    wireType
691}
692
693// typeInfoMap is an atomic pointer to map[reflect.Type]*typeInfo.
694// It's updated copy-on-write. Readers just do an atomic load
695// to get the current version of the map. Writers make a full copy of
696// the map and atomically update the pointer to point to the new map.
697// Under heavy read contention, this is significantly faster than a map
698// protected by a mutex.
699var typeInfoMap atomic.Value
700
701// typeInfoMapInit is used instead of typeInfoMap during init time,
702// as types are registered sequentially during init and we can save
703// the overhead of making map copies.
704// It is saved to typeInfoMap and set to nil before init finishes.
705var typeInfoMapInit = make(map[reflect.Type]*typeInfo, 16)
706
707func lookupTypeInfo(rt reflect.Type) *typeInfo {
708	if m := typeInfoMapInit; m != nil {
709		return m[rt]
710	}
711	m, _ := typeInfoMap.Load().(map[reflect.Type]*typeInfo)
712	return m[rt]
713}
714
715func getTypeInfo(ut *userTypeInfo) (*typeInfo, error) {
716	rt := ut.base
717	if ut.externalEnc != 0 {
718		// We want the user type, not the base type.
719		rt = ut.user
720	}
721	if info := lookupTypeInfo(rt); info != nil {
722		return info, nil
723	}
724	return buildTypeInfo(ut, rt)
725}
726
727// buildTypeInfo constructs the type information for the type
728// and stores it in the type info map.
729func buildTypeInfo(ut *userTypeInfo, rt reflect.Type) (*typeInfo, error) {
730	typeLock.Lock()
731	defer typeLock.Unlock()
732
733	if info := lookupTypeInfo(rt); info != nil {
734		return info, nil
735	}
736
737	gt, err := getBaseType(rt.Name(), rt)
738	if err != nil {
739		return nil, err
740	}
741	info := &typeInfo{id: gt.id()}
742
743	if ut.externalEnc != 0 {
744		userType, err := getType(rt.Name(), ut, rt)
745		if err != nil {
746			return nil, err
747		}
748		gt := userType.id().gobType().(*gobEncoderType)
749		switch ut.externalEnc {
750		case xGob:
751			info.wire.GobEncoderT = gt
752		case xBinary:
753			info.wire.BinaryMarshalerT = gt
754		case xText:
755			info.wire.TextMarshalerT = gt
756		}
757		rt = ut.user
758	} else {
759		t := info.id.gobType()
760		switch typ := rt; typ.Kind() {
761		case reflect.Array:
762			info.wire.ArrayT = t.(*arrayType)
763		case reflect.Map:
764			info.wire.MapT = t.(*mapType)
765		case reflect.Slice:
766			// []byte == []uint8 is a special case handled separately
767			if typ.Elem().Kind() != reflect.Uint8 {
768				info.wire.SliceT = t.(*sliceType)
769			}
770		case reflect.Struct:
771			info.wire.StructT = t.(*structType)
772		}
773	}
774
775	if m := typeInfoMapInit; m != nil {
776		m[rt] = info
777		return info, nil
778	}
779
780	// Create new map with old contents plus new entry.
781	m, _ := typeInfoMap.Load().(map[reflect.Type]*typeInfo)
782	newm := make(map[reflect.Type]*typeInfo, len(m))
783	for k, v := range m {
784		newm[k] = v
785	}
786	newm[rt] = info
787	typeInfoMap.Store(newm)
788	return info, nil
789}
790
791// Called only when a panic is acceptable and unexpected.
792func mustGetTypeInfo(rt reflect.Type) *typeInfo {
793	t, err := getTypeInfo(userType(rt))
794	if err != nil {
795		panic("getTypeInfo: " + err.Error())
796	}
797	return t
798}
799
800// GobEncoder is the interface describing data that provides its own
801// representation for encoding values for transmission to a GobDecoder.
802// A type that implements GobEncoder and GobDecoder has complete
803// control over the representation of its data and may therefore
804// contain things such as private fields, channels, and functions,
805// which are not usually transmissible in gob streams.
806//
807// Note: Since gobs can be stored permanently, it is good design
808// to guarantee the encoding used by a GobEncoder is stable as the
809// software evolves. For instance, it might make sense for GobEncode
810// to include a version number in the encoding.
811type GobEncoder interface {
812	// GobEncode returns a byte slice representing the encoding of the
813	// receiver for transmission to a GobDecoder, usually of the same
814	// concrete type.
815	GobEncode() ([]byte, error)
816}
817
818// GobDecoder is the interface describing data that provides its own
819// routine for decoding transmitted values sent by a GobEncoder.
820type GobDecoder interface {
821	// GobDecode overwrites the receiver, which must be a pointer,
822	// with the value represented by the byte slice, which was written
823	// by GobEncode, usually for the same concrete type.
824	GobDecode([]byte) error
825}
826
827var (
828	nameToConcreteType sync.Map // map[string]reflect.Type
829	concreteTypeToName sync.Map // map[reflect.Type]string
830)
831
832// RegisterName is like [Register] but uses the provided name rather than the
833// type's default.
834func RegisterName(name string, value any) {
835	if name == "" {
836		// reserved for nil
837		panic("attempt to register empty name")
838	}
839
840	ut := userType(reflect.TypeOf(value))
841
842	// Check for incompatible duplicates. The name must refer to the
843	// same user type, and vice versa.
844
845	// Store the name and type provided by the user....
846	if t, dup := nameToConcreteType.LoadOrStore(name, reflect.TypeOf(value)); dup && t != ut.user {
847		panic(fmt.Sprintf("gob: registering duplicate types for %q: %s != %s", name, t, ut.user))
848	}
849
850	// but the flattened type in the type table, since that's what decode needs.
851	if n, dup := concreteTypeToName.LoadOrStore(ut.base, name); dup && n != name {
852		nameToConcreteType.Delete(name)
853		panic(fmt.Sprintf("gob: registering duplicate names for %s: %q != %q", ut.user, n, name))
854	}
855}
856
857// Register records a type, identified by a value for that type, under its
858// internal type name. That name will identify the concrete type of a value
859// sent or received as an interface variable. Only types that will be
860// transferred as implementations of interface values need to be registered.
861// Expecting to be used only during initialization, it panics if the mapping
862// between types and names is not a bijection.
863func Register(value any) {
864	// Default to printed representation for unnamed types
865	rt := reflect.TypeOf(value)
866	name := rt.String()
867
868	// But for named types (or pointers to them), qualify with import path (but see inner comment).
869	// Dereference one pointer looking for a named type.
870	star := ""
871	if rt.Name() == "" {
872		if pt := rt; pt.Kind() == reflect.Pointer {
873			star = "*"
874			// NOTE: The following line should be rt = pt.Elem() to implement
875			// what the comment above claims, but fixing it would break compatibility
876			// with existing gobs.
877			//
878			// Given package p imported as "full/p" with these definitions:
879			//     package p
880			//     type T1 struct { ... }
881			// this table shows the intended and actual strings used by gob to
882			// name the types:
883			//
884			// Type      Correct string     Actual string
885			//
886			// T1        full/p.T1          full/p.T1
887			// *T1       *full/p.T1         *p.T1
888			//
889			// The missing full path cannot be fixed without breaking existing gob decoders.
890			rt = pt
891		}
892	}
893	if rt.Name() != "" {
894		if rt.PkgPath() == "" {
895			name = star + rt.Name()
896		} else {
897			name = star + rt.PkgPath() + "." + rt.Name()
898		}
899	}
900
901	RegisterName(name, value)
902}
903
904func registerBasics() {
905	Register(int(0))
906	Register(int8(0))
907	Register(int16(0))
908	Register(int32(0))
909	Register(int64(0))
910	Register(uint(0))
911	Register(uint8(0))
912	Register(uint16(0))
913	Register(uint32(0))
914	Register(uint64(0))
915	Register(float32(0))
916	Register(float64(0))
917	Register(complex64(0i))
918	Register(complex128(0i))
919	Register(uintptr(0))
920	Register(false)
921	Register("")
922	Register([]byte(nil))
923	Register([]int(nil))
924	Register([]int8(nil))
925	Register([]int16(nil))
926	Register([]int32(nil))
927	Register([]int64(nil))
928	Register([]uint(nil))
929	Register([]uint8(nil))
930	Register([]uint16(nil))
931	Register([]uint32(nil))
932	Register([]uint64(nil))
933	Register([]float32(nil))
934	Register([]float64(nil))
935	Register([]complex64(nil))
936	Register([]complex128(nil))
937	Register([]uintptr(nil))
938	Register([]bool(nil))
939	Register([]string(nil))
940}
941
942func init() {
943	typeInfoMap.Store(typeInfoMapInit)
944	typeInfoMapInit = nil
945}
946