// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package gob

import (
	
	
	
	
	
	
	
	
	
)

// userTypeInfo stores the information associated with a type the user has handed
// to the package. It's computed once and stored in a map keyed by reflection
// type.
type userTypeInfo struct {
	user        reflect.Type // the type the user handed us
	base        reflect.Type // the base type after all indirections
	indir       int          // number of indirections to reach the base type
	externalEnc int          // xGob, xBinary, or xText
	externalDec int          // xGob, xBinary, or xText
	encIndir    int8         // number of indirections to reach the receiver type; may be negative
	decIndir    int8         // number of indirections to reach the receiver type; may be negative
}

// externalEncoding bits
const (
	xGob    = 1 + iota // GobEncoder or GobDecoder
	xBinary            // encoding.BinaryMarshaler or encoding.BinaryUnmarshaler
	xText              // encoding.TextMarshaler or encoding.TextUnmarshaler
)

var userTypeCache sync.Map // map[reflect.Type]*userTypeInfo

// validUserType returns, and saves, the information associated with user-provided type rt.
// If the user type is not valid, err will be non-nil. To be used when the error handler
// is not set up.
func validUserType( reflect.Type) (*userTypeInfo, error) {
	if ,  := userTypeCache.Load();  {
		return .(*userTypeInfo), nil
	}

	// Construct a new userTypeInfo and atomically add it to the userTypeCache.
	// If we lose the race, we'll waste a little CPU and create a little garbage
	// but return the existing value anyway.

	 := new(userTypeInfo)
	.base = 
	.user = 
	// A type that is just a cycle of pointers (such as type T *T) cannot
	// be represented in gobs, which need some concrete data. We use a
	// cycle detection algorithm from Knuth, Vol 2, Section 3.1, Ex 6,
	// pp 539-540.  As we step through indirections, run another type at
	// half speed. If they meet up, there's a cycle.
	 := .base // walks half as fast as ut.base
	for {
		 := .base
		if .Kind() != reflect.Pointer {
			break
		}
		.base = .Elem()
		if .base ==  { // ut.base lapped slowpoke
			// recursive pointer type.
			return nil, errors.New("can't represent recursive pointer type " + .base.String())
		}
		if .indir%2 == 0 {
			 = .Elem()
		}
		.indir++
	}

	if ,  := implementsInterface(.user, gobEncoderInterfaceType);  {
		.externalEnc, .encIndir = xGob, 
	} else if ,  := implementsInterface(.user, binaryMarshalerInterfaceType);  {
		.externalEnc, .encIndir = xBinary, 
	}

	// NOTE(rsc): Would like to allow MarshalText here, but results in incompatibility
	// with older encodings for net.IP. See golang.org/issue/6760.
	// } else if ok, indir := implementsInterface(ut.user, textMarshalerInterfaceType); ok {
	// 	ut.externalEnc, ut.encIndir = xText, indir
	// }

	if ,  := implementsInterface(.user, gobDecoderInterfaceType);  {
		.externalDec, .decIndir = xGob, 
	} else if ,  := implementsInterface(.user, binaryUnmarshalerInterfaceType);  {
		.externalDec, .decIndir = xBinary, 
	}

	// See note above.
	// } else if ok, indir := implementsInterface(ut.user, textUnmarshalerInterfaceType); ok {
	// 	ut.externalDec, ut.decIndir = xText, indir
	// }

	,  := userTypeCache.LoadOrStore(, )
	return .(*userTypeInfo), nil
}

var (
	gobEncoderInterfaceType        = reflect.TypeFor[GobEncoder]()
	gobDecoderInterfaceType        = reflect.TypeFor[GobDecoder]()
	binaryMarshalerInterfaceType   = reflect.TypeFor[encoding.BinaryMarshaler]()
	binaryUnmarshalerInterfaceType = reflect.TypeFor[encoding.BinaryUnmarshaler]()
	textMarshalerInterfaceType     = reflect.TypeFor[encoding.TextMarshaler]()
	textUnmarshalerInterfaceType   = reflect.TypeFor[encoding.TextUnmarshaler]()

	wireTypeType = reflect.TypeFor[wireType]()
)

// implementsInterface reports whether the type implements the
// gobEncoder/gobDecoder interface.
// It also returns the number of indirections required to get to the
// implementation.
func implementsInterface(,  reflect.Type) ( bool,  int8) {
	if  == nil {
		return
	}
	 := 
	// The type might be a pointer and we need to keep
	// dereferencing to the base type until we find an implementation.
	for {
		if .Implements() {
			return true, 
		}
		if  := ; .Kind() == reflect.Pointer {
			++
			if  > 100 { // insane number of indirections
				return false, 0
			}
			 = .Elem()
			continue
		}
		break
	}
	// No luck yet, but if this is a base type (non-pointer), the pointer might satisfy.
	if .Kind() != reflect.Pointer {
		// Not a pointer, but does the pointer work?
		if reflect.PointerTo().Implements() {
			return true, -1
		}
	}
	return false, 0
}

// userType returns, and saves, the information associated with user-provided type rt.
// If the user type is not valid, it calls error.
func userType( reflect.Type) *userTypeInfo {
	,  := validUserType()
	if  != nil {
		error_()
	}
	return 
}

// A typeId represents a gob Type as an integer that can be passed on the wire.
// Internally, typeIds are used as keys to a map to recover the underlying type info.
type typeId int32

var typeLock sync.Mutex // set while building a type
const firstUserId = 64  // lowest id number granted to user

type gobType interface {
	id() typeId
	setId(id typeId)
	name() string
	string() string // not public; only for debugging
	safeString(seen map[typeId]bool) string
}

var (
	types                = make(map[reflect.Type]gobType, 32)
	idToTypeSlice        = make([]gobType, 1, firstUserId)
	builtinIdToTypeSlice [firstUserId]gobType // set in init() after builtins are established
)

func idToType( typeId) gobType {
	if  < 0 || int() >= len(idToTypeSlice) {
		return nil
	}
	return idToTypeSlice[]
}

func builtinIdToType( typeId) gobType {
	if  < 0 || int() >= len(builtinIdToTypeSlice) {
		return nil
	}
	return builtinIdToTypeSlice[]
}

func setTypeId( gobType) {
	// When building recursive types, someone may get there before us.
	if .id() != 0 {
		return
	}
	 := typeId(len(idToTypeSlice))
	.setId()
	idToTypeSlice = append(idToTypeSlice, )
}

func ( typeId) () gobType {
	if  == 0 {
		return nil
	}
	return idToType()
}

// string returns the string representation of the type associated with the typeId.
func ( typeId) () string {
	if .gobType() == nil {
		return "<nil>"
	}
	return .gobType().string()
}

// Name returns the name of the type associated with the typeId.
func ( typeId) () string {
	if .gobType() == nil {
		return "<nil>"
	}
	return .gobType().name()
}

// CommonType holds elements of all types.
// It is a historical artifact, kept for binary compatibility and exported
// only for the benefit of the package's encoding of type descriptors. It is
// not intended for direct use by clients.
type CommonType struct {
	Name string
	Id   typeId
}

func ( *CommonType) () typeId { return .Id }

func ( *CommonType) ( typeId) { .Id =  }

func ( *CommonType) () string { return .Name }

func ( *CommonType) ( map[typeId]bool) string {
	return .Name
}

func ( *CommonType) () string { return .Name }

// Create and check predefined types
// The string for tBytes is "bytes" not "[]byte" to signify its specialness.

var (
	// Primordial types, needed during initialization.
	// Always passed as pointers so the interface{} type
	// goes through without losing its interfaceness.
	tBool      = bootstrapType("bool", (*bool)(nil))
	tInt       = bootstrapType("int", (*int)(nil))
	tUint      = bootstrapType("uint", (*uint)(nil))
	tFloat     = bootstrapType("float", (*float64)(nil))
	tBytes     = bootstrapType("bytes", (*[]byte)(nil))
	tString    = bootstrapType("string", (*string)(nil))
	tComplex   = bootstrapType("complex", (*complex128)(nil))
	tInterface = bootstrapType("interface", (*any)(nil))
	// Reserve some Ids for compatible expansion
	tReserved7 = bootstrapType("_reserved1", (*struct{ r7 int })(nil))
	tReserved6 = bootstrapType("_reserved1", (*struct{ r6 int })(nil))
	tReserved5 = bootstrapType("_reserved1", (*struct{ r5 int })(nil))
	tReserved4 = bootstrapType("_reserved1", (*struct{ r4 int })(nil))
	tReserved3 = bootstrapType("_reserved1", (*struct{ r3 int })(nil))
	tReserved2 = bootstrapType("_reserved1", (*struct{ r2 int })(nil))
	tReserved1 = bootstrapType("_reserved1", (*struct{ r1 int })(nil))
)

// Predefined because it's needed by the Decoder
var tWireType = mustGetTypeInfo(wireTypeType).id
var wireTypeUserInfo *userTypeInfo // userTypeInfo of wireType

func init() {
	// Some magic numbers to make sure there are no surprises.
	checkId(16, tWireType)
	checkId(17, mustGetTypeInfo(reflect.TypeFor[arrayType]()).id)
	checkId(18, mustGetTypeInfo(reflect.TypeFor[CommonType]()).id)
	checkId(19, mustGetTypeInfo(reflect.TypeFor[sliceType]()).id)
	checkId(20, mustGetTypeInfo(reflect.TypeFor[structType]()).id)
	checkId(21, mustGetTypeInfo(reflect.TypeFor[fieldType]()).id)
	checkId(23, mustGetTypeInfo(reflect.TypeFor[mapType]()).id)

	copy(builtinIdToTypeSlice[:], idToTypeSlice)

	// Move the id space upwards to allow for growth in the predefined world
	// without breaking existing files.
	if  := len(idToTypeSlice);  > firstUserId {
		panic(fmt.Sprintln("nextId too large:", ))
	}
	idToTypeSlice = idToTypeSlice[:firstUserId]
	registerBasics()
	wireTypeUserInfo = userType(wireTypeType)
}

// Array type
type arrayType struct {
	CommonType
	Elem typeId
	Len  int
}

func newArrayType( string) *arrayType {
	 := &arrayType{CommonType{Name: }, 0, 0}
	return 
}

func ( *arrayType) ( gobType,  int) {
	// Set our type id before evaluating the element's, in case it's our own.
	setTypeId()
	.Elem = .id()
	.Len = 
}

func ( *arrayType) ( map[typeId]bool) string {
	if [.Id] {
		return .Name
	}
	[.Id] = true
	return fmt.Sprintf("[%d]%s", .Len, .Elem.gobType().safeString())
}

func ( *arrayType) () string { return .safeString(make(map[typeId]bool)) }

// GobEncoder type (something that implements the GobEncoder interface)
type gobEncoderType struct {
	CommonType
}

func newGobEncoderType( string) *gobEncoderType {
	 := &gobEncoderType{CommonType{Name: }}
	setTypeId()
	return 
}

func ( *gobEncoderType) ( map[typeId]bool) string {
	return .Name
}

func ( *gobEncoderType) () string { return .Name }

// Map type
type mapType struct {
	CommonType
	Key  typeId
	Elem typeId
}

func newMapType( string) *mapType {
	 := &mapType{CommonType{Name: }, 0, 0}
	return 
}

func ( *mapType) (,  gobType) {
	// Set our type id before evaluating the element's, in case it's our own.
	setTypeId()
	.Key = .id()
	.Elem = .id()
}

func ( *mapType) ( map[typeId]bool) string {
	if [.Id] {
		return .Name
	}
	[.Id] = true
	 := .Key.gobType().safeString()
	 := .Elem.gobType().safeString()
	return fmt.Sprintf("map[%s]%s", , )
}

func ( *mapType) () string { return .safeString(make(map[typeId]bool)) }

// Slice type
type sliceType struct {
	CommonType
	Elem typeId
}

func newSliceType( string) *sliceType {
	 := &sliceType{CommonType{Name: }, 0}
	return 
}

func ( *sliceType) ( gobType) {
	// Set our type id before evaluating the element's, in case it's our own.
	setTypeId()
	// See the comments about ids in newTypeObject. Only slices and
	// structs have mutual recursion.
	if .id() == 0 {
		setTypeId()
	}
	.Elem = .id()
}

func ( *sliceType) ( map[typeId]bool) string {
	if [.Id] {
		return .Name
	}
	[.Id] = true
	return fmt.Sprintf("[]%s", .Elem.gobType().safeString())
}

func ( *sliceType) () string { return .safeString(make(map[typeId]bool)) }

// Struct type
type fieldType struct {
	Name string
	Id   typeId
}

type structType struct {
	CommonType
	Field []fieldType
}

func ( *structType) ( map[typeId]bool) string {
	if  == nil {
		return "<nil>"
	}
	if ,  := [.Id];  {
		return .Name
	}
	[.Id] = true
	 := .Name + " = struct { "
	for ,  := range .Field {
		 += fmt.Sprintf("%s %s; ", .Name, .Id.gobType().safeString())
	}
	 += "}"
	return 
}

func ( *structType) () string { return .safeString(make(map[typeId]bool)) }

func newStructType( string) *structType {
	 := &structType{CommonType{Name: }, nil}
	// For historical reasons we set the id here rather than init.
	// See the comment in newTypeObject for details.
	setTypeId()
	return 
}

// newTypeObject allocates a gobType for the reflection type rt.
// Unless ut represents a GobEncoder, rt should be the base type
// of ut.
// This is only called from the encoding side. The decoding side
// works through typeIds and userTypeInfos alone.
func newTypeObject( string,  *userTypeInfo,  reflect.Type) (gobType, error) {
	// Does this type implement GobEncoder?
	if .externalEnc != 0 {
		return newGobEncoderType(), nil
	}
	var  error
	var ,  gobType
	defer func() {
		if  != nil {
			delete(types, )
		}
	}()
	// Install the top-level type before the subtypes (e.g. struct before
	// fields) so recursive types can be constructed safely.
	switch  := ; .Kind() {
	// All basic types are easy: they are predefined.
	case reflect.Bool:
		return tBool.gobType(), nil

	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return tInt.gobType(), nil

	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		return tUint.gobType(), nil

	case reflect.Float32, reflect.Float64:
		return tFloat.gobType(), nil

	case reflect.Complex64, reflect.Complex128:
		return tComplex.gobType(), nil

	case reflect.String:
		return tString.gobType(), nil

	case reflect.Interface:
		return tInterface.gobType(), nil

	case reflect.Array:
		 := newArrayType()
		types[] = 
		,  = getBaseType("", .Elem())
		if  != nil {
			return nil, 
		}
		// Historical aside:
		// For arrays, maps, and slices, we set the type id after the elements
		// are constructed. This is to retain the order of type id allocation after
		// a fix made to handle recursive types, which changed the order in
		// which types are built. Delaying the setting in this way preserves
		// type ids while allowing recursive types to be described. Structs,
		// done below, were already handling recursion correctly so they
		// assign the top-level id before those of the field.
		.init(, .Len())
		return , nil

	case reflect.Map:
		 := newMapType()
		types[] = 
		,  = getBaseType("", .Key())
		if  != nil {
			return nil, 
		}
		,  = getBaseType("", .Elem())
		if  != nil {
			return nil, 
		}
		.init(, )
		return , nil

	case reflect.Slice:
		// []byte == []uint8 is a special case
		if .Elem().Kind() == reflect.Uint8 {
			return tBytes.gobType(), nil
		}
		 := newSliceType()
		types[] = 
		,  = getBaseType(.Elem().Name(), .Elem())
		if  != nil {
			return nil, 
		}
		.init()
		return , nil

	case reflect.Struct:
		 := newStructType()
		types[] = 
		idToTypeSlice[.id()] = 
		for  := 0;  < .NumField(); ++ {
			 := .Field()
			if !isSent(&) {
				continue
			}
			 := userType(.Type).base
			 := .Name()
			if  == "" {
				 := userType(.Type).base
				 = .String()
			}
			,  := getBaseType(, .Type)
			if  != nil {
				return nil, 
			}
			// Some mutually recursive types can cause us to be here while
			// still defining the element. Fix the element type id here.
			// We could do this more neatly by setting the id at the start of
			// building every type, but that would break binary compatibility.
			if .id() == 0 {
				setTypeId()
			}
			.Field = append(.Field, fieldType{.Name, .id()})
		}
		return , nil

	default:
		return nil, errors.New("gob NewTypeObject can't handle type: " + .String())
	}
}

// isExported reports whether this is an exported - upper case - name.
func isExported( string) bool {
	,  := utf8.DecodeRuneInString()
	return unicode.IsUpper()
}

// isSent reports whether this struct field is to be transmitted.
// It will be transmitted only if it is exported and not a chan or func field
// or pointer to chan or func.
func isSent( *reflect.StructField) bool {
	if !isExported(.Name) {
		return false
	}
	// If the field is a chan or func or pointer thereto, don't send it.
	// That is, treat it like an unexported field.
	 := .Type
	for .Kind() == reflect.Pointer {
		 = .Elem()
	}
	if .Kind() == reflect.Chan || .Kind() == reflect.Func {
		return false
	}
	return true
}

// getBaseType returns the Gob type describing the given reflect.Type's base type.
// typeLock must be held.
func getBaseType( string,  reflect.Type) (gobType, error) {
	 := userType()
	return getType(, , .base)
}

// getType returns the Gob type describing the given reflect.Type.
// Should be called only when handling GobEncoders/Decoders,
// which may be pointers. All other types are handled through the
// base type, never a pointer.
// typeLock must be held.
func getType( string,  *userTypeInfo,  reflect.Type) (gobType, error) {
	,  := types[]
	if  {
		return , nil
	}
	,  := newTypeObject(, , )
	if  == nil {
		types[] = 
	}
	return , 
}

func checkId(,  typeId) {
	if  !=  {
		fmt.Fprintf(os.Stderr, "checkId: %d should be %d\n", int(), int())
		panic("bootstrap type wrong id: " + .name() + " " + .string() + " not " + .string())
	}
}

// used for building the basic types; called only from init().  the incoming
// interface always refers to a pointer.
func bootstrapType( string,  any) typeId {
	 := reflect.TypeOf().Elem()
	,  := types[]
	if  {
		panic("bootstrap type already present: " +  + ", " + .String())
	}
	 := &CommonType{Name: }
	types[] = 
	setTypeId()
	return .id()
}

// Representation of the information we send and receive about this type.
// Each value we send is preceded by its type definition: an encoded int.
// However, the very first time we send the value, we first send the pair
// (-id, wireType).
// For bootstrapping purposes, we assume that the recipient knows how
// to decode a wireType; it is exactly the wireType struct here, interpreted
// using the gob rules for sending a structure, except that we assume the
// ids for wireType and structType etc. are known. The relevant pieces
// are built in encode.go's init() function.
// To maintain binary compatibility, if you extend this type, always put
// the new fields last.
type wireType struct {
	ArrayT           *arrayType
	SliceT           *sliceType
	StructT          *structType
	MapT             *mapType
	GobEncoderT      *gobEncoderType
	BinaryMarshalerT *gobEncoderType
	TextMarshalerT   *gobEncoderType
}

func ( *wireType) () string {
	const  = "unknown type"
	if  == nil {
		return 
	}
	switch {
	case .ArrayT != nil:
		return .ArrayT.Name
	case .SliceT != nil:
		return .SliceT.Name
	case .StructT != nil:
		return .StructT.Name
	case .MapT != nil:
		return .MapT.Name
	case .GobEncoderT != nil:
		return .GobEncoderT.Name
	case .BinaryMarshalerT != nil:
		return .BinaryMarshalerT.Name
	case .TextMarshalerT != nil:
		return .TextMarshalerT.Name
	}
	return 
}

type typeInfo struct {
	id      typeId
	encInit sync.Mutex // protects creation of encoder
	encoder atomic.Pointer[encEngine]
	wire    wireType
}

// typeInfoMap is an atomic pointer to map[reflect.Type]*typeInfo.
// It's updated copy-on-write. Readers just do an atomic load
// to get the current version of the map. Writers make a full copy of
// the map and atomically update the pointer to point to the new map.
// Under heavy read contention, this is significantly faster than a map
// protected by a mutex.
var typeInfoMap atomic.Value

// typeInfoMapInit is used instead of typeInfoMap during init time,
// as types are registered sequentially during init and we can save
// the overhead of making map copies.
// It is saved to typeInfoMap and set to nil before init finishes.
var typeInfoMapInit = make(map[reflect.Type]*typeInfo, 16)

func lookupTypeInfo( reflect.Type) *typeInfo {
	if  := typeInfoMapInit;  != nil {
		return []
	}
	,  := typeInfoMap.Load().(map[reflect.Type]*typeInfo)
	return []
}

func getTypeInfo( *userTypeInfo) (*typeInfo, error) {
	 := .base
	if .externalEnc != 0 {
		// We want the user type, not the base type.
		 = .user
	}
	if  := lookupTypeInfo();  != nil {
		return , nil
	}
	return buildTypeInfo(, )
}

// buildTypeInfo constructs the type information for the type
// and stores it in the type info map.
func buildTypeInfo( *userTypeInfo,  reflect.Type) (*typeInfo, error) {
	typeLock.Lock()
	defer typeLock.Unlock()

	if  := lookupTypeInfo();  != nil {
		return , nil
	}

	,  := getBaseType(.Name(), )
	if  != nil {
		return nil, 
	}
	 := &typeInfo{id: .id()}

	if .externalEnc != 0 {
		,  := getType(.Name(), , )
		if  != nil {
			return nil, 
		}
		 := .id().gobType().(*gobEncoderType)
		switch .externalEnc {
		case xGob:
			.wire.GobEncoderT = 
		case xBinary:
			.wire.BinaryMarshalerT = 
		case xText:
			.wire.TextMarshalerT = 
		}
		 = .user
	} else {
		 := .id.gobType()
		switch  := ; .Kind() {
		case reflect.Array:
			.wire.ArrayT = .(*arrayType)
		case reflect.Map:
			.wire.MapT = .(*mapType)
		case reflect.Slice:
			// []byte == []uint8 is a special case handled separately
			if .Elem().Kind() != reflect.Uint8 {
				.wire.SliceT = .(*sliceType)
			}
		case reflect.Struct:
			.wire.StructT = .(*structType)
		}
	}

	if  := typeInfoMapInit;  != nil {
		[] = 
		return , nil
	}

	// Create new map with old contents plus new entry.
	,  := typeInfoMap.Load().(map[reflect.Type]*typeInfo)
	 := make(map[reflect.Type]*typeInfo, len())
	for ,  := range  {
		[] = 
	}
	[] = 
	typeInfoMap.Store()
	return , nil
}

// Called only when a panic is acceptable and unexpected.
func mustGetTypeInfo( reflect.Type) *typeInfo {
	,  := getTypeInfo(userType())
	if  != nil {
		panic("getTypeInfo: " + .Error())
	}
	return 
}

// GobEncoder is the interface describing data that provides its own
// representation for encoding values for transmission to a GobDecoder.
// A type that implements GobEncoder and GobDecoder has complete
// control over the representation of its data and may therefore
// contain things such as private fields, channels, and functions,
// which are not usually transmissible in gob streams.
//
// Note: Since gobs can be stored permanently, it is good design
// to guarantee the encoding used by a GobEncoder is stable as the
// software evolves. For instance, it might make sense for GobEncode
// to include a version number in the encoding.
type GobEncoder interface {
	// GobEncode returns a byte slice representing the encoding of the
	// receiver for transmission to a GobDecoder, usually of the same
	// concrete type.
	GobEncode() ([]byte, error)
}

// GobDecoder is the interface describing data that provides its own
// routine for decoding transmitted values sent by a GobEncoder.
type GobDecoder interface {
	// GobDecode overwrites the receiver, which must be a pointer,
	// with the value represented by the byte slice, which was written
	// by GobEncode, usually for the same concrete type.
	GobDecode([]byte) error
}

var (
	nameToConcreteType sync.Map // map[string]reflect.Type
	concreteTypeToName sync.Map // map[reflect.Type]string
)

// RegisterName is like [Register] but uses the provided name rather than the
// type's default.
func ( string,  any) {
	if  == "" {
		// reserved for nil
		panic("attempt to register empty name")
	}

	 := userType(reflect.TypeOf())

	// Check for incompatible duplicates. The name must refer to the
	// same user type, and vice versa.

	// Store the name and type provided by the user....
	if ,  := nameToConcreteType.LoadOrStore(, reflect.TypeOf());  &&  != .user {
		panic(fmt.Sprintf("gob: registering duplicate types for %q: %s != %s", , , .user))
	}

	// but the flattened type in the type table, since that's what decode needs.
	if ,  := concreteTypeToName.LoadOrStore(.base, );  &&  !=  {
		nameToConcreteType.Delete()
		panic(fmt.Sprintf("gob: registering duplicate names for %s: %q != %q", .user, , ))
	}
}

// Register records a type, identified by a value for that type, under its
// internal type name. That name will identify the concrete type of a value
// sent or received as an interface variable. Only types that will be
// transferred as implementations of interface values need to be registered.
// Expecting to be used only during initialization, it panics if the mapping
// between types and names is not a bijection.
func ( any) {
	// Default to printed representation for unnamed types
	 := reflect.TypeOf()
	 := .String()

	// But for named types (or pointers to them), qualify with import path (but see inner comment).
	// Dereference one pointer looking for a named type.
	 := ""
	if .Name() == "" {
		if  := ; .Kind() == reflect.Pointer {
			 = "*"
			// NOTE: The following line should be rt = pt.Elem() to implement
			// what the comment above claims, but fixing it would break compatibility
			// with existing gobs.
			//
			// Given package p imported as "full/p" with these definitions:
			//     package p
			//     type T1 struct { ... }
			// this table shows the intended and actual strings used by gob to
			// name the types:
			//
			// Type      Correct string     Actual string
			//
			// T1        full/p.T1          full/p.T1
			// *T1       *full/p.T1         *p.T1
			//
			// The missing full path cannot be fixed without breaking existing gob decoders.
			 = 
		}
	}
	if .Name() != "" {
		if .PkgPath() == "" {
			 =  + .Name()
		} else {
			 =  + .PkgPath() + "." + .Name()
		}
	}

	RegisterName(, )
}

func registerBasics() {
	Register(int(0))
	Register(int8(0))
	Register(int16(0))
	Register(int32(0))
	Register(int64(0))
	Register(uint(0))
	Register(uint8(0))
	Register(uint16(0))
	Register(uint32(0))
	Register(uint64(0))
	Register(float32(0))
	Register(float64(0))
	Register(complex64(0i))
	Register(complex128(0i))
	Register(uintptr(0))
	Register(false)
	Register("")
	Register([]byte(nil))
	Register([]int(nil))
	Register([]int8(nil))
	Register([]int16(nil))
	Register([]int32(nil))
	Register([]int64(nil))
	Register([]uint(nil))
	Register([]uint8(nil))
	Register([]uint16(nil))
	Register([]uint32(nil))
	Register([]uint64(nil))
	Register([]float32(nil))
	Register([]float64(nil))
	Register([]complex64(nil))
	Register([]complex128(nil))
	Register([]uintptr(nil))
	Register([]bool(nil))
	Register([]string(nil))
}

func init() {
	typeInfoMap.Store(typeInfoMapInit)
	typeInfoMapInit = nil
}