The Go Programming Language

Source file src/pkg/gob/type.go

     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	
     5	package gob
     6	
     7	import (
     8		"fmt"
     9		"os"
    10		"reflect"
    11		"sync"
    12		"unicode"
    13		"utf8"
    14	)
    15	
    16	// userTypeInfo stores the information associated with a type the user has handed
    17	// to the package.  It's computed once and stored in a map keyed by reflection
    18	// type.
    19	type userTypeInfo struct {
    20		user         reflect.Type // the type the user handed us
    21		base         reflect.Type // the base type after all indirections
    22		indir        int          // number of indirections to reach the base type
    23		isGobEncoder bool         // does the type implement GobEncoder?
    24		isGobDecoder bool         // does the type implement GobDecoder?
    25		encIndir     int8         // number of indirections to reach the receiver type; may be negative
    26		decIndir     int8         // number of indirections to reach the receiver type; may be negative
    27	}
    28	
    29	var (
    30		// Protected by an RWMutex because we read it a lot and write
    31		// it only when we see a new type, typically when compiling.
    32		userTypeLock  sync.RWMutex
    33		userTypeCache = make(map[reflect.Type]*userTypeInfo)
    34	)
    35	
    36	// validType returns, and saves, the information associated with user-provided type rt.
    37	// If the user type is not valid, err will be non-nil.  To be used when the error handler
    38	// is not set up.
    39	func validUserType(rt reflect.Type) (ut *userTypeInfo, err os.Error) {
    40		userTypeLock.RLock()
    41		ut = userTypeCache[rt]
    42		userTypeLock.RUnlock()
    43		if ut != nil {
    44			return
    45		}
    46		// Now set the value under the write lock.
    47		userTypeLock.Lock()
    48		defer userTypeLock.Unlock()
    49		if ut = userTypeCache[rt]; ut != nil {
    50			// Lost the race; not a problem.
    51			return
    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.Ptr {
    65				break
    66			}
    67			ut.base = pt.Elem()
    68			if ut.base == slowpoke { // ut.base lapped slowpoke
    69				// recursive pointer type.
    70				return nil, os.NewError("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		ut.isGobEncoder, ut.encIndir = implementsInterface(ut.user, gobEncoderInterfaceType)
    78		ut.isGobDecoder, ut.decIndir = implementsInterface(ut.user, gobDecoderInterfaceType)
    79		userTypeCache[rt] = ut
    80		return
    81	}
    82	
    83	var (
    84		gobEncoderInterfaceType = reflect.TypeOf((*GobEncoder)(nil)).Elem()
    85		gobDecoderInterfaceType = reflect.TypeOf((*GobDecoder)(nil)).Elem()
    86	)
    87	
    88	// implementsInterface reports whether the type implements the
    89	// gobEncoder/gobDecoder interface.
    90	// It also returns the number of indirections required to get to the
    91	// implementation.
    92	func implementsInterface(typ, gobEncDecType reflect.Type) (success bool, indir int8) {
    93		if typ == nil {
    94			return
    95		}
    96		rt := typ
    97		// The type might be a pointer and we need to keep
    98		// dereferencing to the base type until we find an implementation.
    99		for {
   100			if rt.Implements(gobEncDecType) {
   101				return true, indir
   102			}
   103			if p := rt; p.Kind() == reflect.Ptr {
   104				indir++
   105				if indir > 100 { // insane number of indirections
   106					return false, 0
   107				}
   108				rt = p.Elem()
   109				continue
   110			}
   111			break
   112		}
   113		// No luck yet, but if this is a base type (non-pointer), the pointer might satisfy.
   114		if typ.Kind() != reflect.Ptr {
   115			// Not a pointer, but does the pointer work?
   116			if reflect.PtrTo(typ).Implements(gobEncDecType) {
   117				return true, -1
   118			}
   119		}
   120		return false, 0
   121	}
   122	
   123	// userType returns, and saves, the information associated with user-provided type rt.
   124	// If the user type is not valid, it calls error.
   125	func userType(rt reflect.Type) *userTypeInfo {
   126		ut, err := validUserType(rt)
   127		if err != nil {
   128			error(err)
   129		}
   130		return ut
   131	}
   132	// A typeId represents a gob Type as an integer that can be passed on the wire.
   133	// Internally, typeIds are used as keys to a map to recover the underlying type info.
   134	type typeId int32
   135	
   136	var nextId typeId       // incremented for each new type we build
   137	var typeLock sync.Mutex // set while building a type
   138	const firstUserId = 64  // lowest id number granted to user
   139	
   140	type gobType interface {
   141		id() typeId
   142		setId(id typeId)
   143		name() string
   144		string() string // not public; only for debugging
   145		safeString(seen map[typeId]bool) string
   146	}
   147	
   148	var types = make(map[reflect.Type]gobType)
   149	var idToType = make(map[typeId]gobType)
   150	var builtinIdToType map[typeId]gobType // set in init() after builtins are established
   151	
   152	func setTypeId(typ gobType) {
   153		nextId++
   154		typ.setId(nextId)
   155		idToType[nextId] = typ
   156	}
   157	
   158	func (t typeId) gobType() gobType {
   159		if t == 0 {
   160			return nil
   161		}
   162		return idToType[t]
   163	}
   164	
   165	// string returns the string representation of the type associated with the typeId.
   166	func (t typeId) string() string {
   167		if t.gobType() == nil {
   168			return "<nil>"
   169		}
   170		return t.gobType().string()
   171	}
   172	
   173	// Name returns the name of the type associated with the typeId.
   174	func (t typeId) name() string {
   175		if t.gobType() == nil {
   176			return "<nil>"
   177		}
   178		return t.gobType().name()
   179	}
   180	
   181	// Common elements of all types.
   182	type CommonType struct {
   183		Name string
   184		Id   typeId
   185	}
   186	
   187	func (t *CommonType) id() typeId { return t.Id }
   188	
   189	func (t *CommonType) setId(id typeId) { t.Id = id }
   190	
   191	func (t *CommonType) string() string { return t.Name }
   192	
   193	func (t *CommonType) safeString(seen map[typeId]bool) string {
   194		return t.Name
   195	}
   196	
   197	func (t *CommonType) name() string { return t.Name }
   198	
   199	// Create and check predefined types
   200	// The string for tBytes is "bytes" not "[]byte" to signify its specialness.
   201	
   202	var (
   203		// Primordial types, needed during initialization.
   204		// Always passed as pointers so the interface{} type
   205		// goes through without losing its interfaceness.
   206		tBool      = bootstrapType("bool", (*bool)(nil), 1)
   207		tInt       = bootstrapType("int", (*int)(nil), 2)
   208		tUint      = bootstrapType("uint", (*uint)(nil), 3)
   209		tFloat     = bootstrapType("float", (*float64)(nil), 4)
   210		tBytes     = bootstrapType("bytes", (*[]byte)(nil), 5)
   211		tString    = bootstrapType("string", (*string)(nil), 6)
   212		tComplex   = bootstrapType("complex", (*complex128)(nil), 7)
   213		tInterface = bootstrapType("interface", (*interface{})(nil), 8)
   214		// Reserve some Ids for compatible expansion
   215		tReserved7 = bootstrapType("_reserved1", (*struct{ r7 int })(nil), 9)
   216		tReserved6 = bootstrapType("_reserved1", (*struct{ r6 int })(nil), 10)
   217		tReserved5 = bootstrapType("_reserved1", (*struct{ r5 int })(nil), 11)
   218		tReserved4 = bootstrapType("_reserved1", (*struct{ r4 int })(nil), 12)
   219		tReserved3 = bootstrapType("_reserved1", (*struct{ r3 int })(nil), 13)
   220		tReserved2 = bootstrapType("_reserved1", (*struct{ r2 int })(nil), 14)
   221		tReserved1 = bootstrapType("_reserved1", (*struct{ r1 int })(nil), 15)
   222	)
   223	
   224	// Predefined because it's needed by the Decoder
   225	var tWireType = mustGetTypeInfo(reflect.TypeOf(wireType{})).id
   226	var wireTypeUserInfo *userTypeInfo // userTypeInfo of (*wireType)
   227	
   228	func init() {
   229		// Some magic numbers to make sure there are no surprises.
   230		checkId(16, tWireType)
   231		checkId(17, mustGetTypeInfo(reflect.TypeOf(arrayType{})).id)
   232		checkId(18, mustGetTypeInfo(reflect.TypeOf(CommonType{})).id)
   233		checkId(19, mustGetTypeInfo(reflect.TypeOf(sliceType{})).id)
   234		checkId(20, mustGetTypeInfo(reflect.TypeOf(structType{})).id)
   235		checkId(21, mustGetTypeInfo(reflect.TypeOf(fieldType{})).id)
   236		checkId(23, mustGetTypeInfo(reflect.TypeOf(mapType{})).id)
   237	
   238		builtinIdToType = make(map[typeId]gobType)
   239		for k, v := range idToType {
   240			builtinIdToType[k] = v
   241		}
   242	
   243		// Move the id space upwards to allow for growth in the predefined world
   244		// without breaking existing files.
   245		if nextId > firstUserId {
   246			panic(fmt.Sprintln("nextId too large:", nextId))
   247		}
   248		nextId = firstUserId
   249		registerBasics()
   250		wireTypeUserInfo = userType(reflect.TypeOf((*wireType)(nil)))
   251	}
   252	
   253	// Array type
   254	type arrayType struct {
   255		CommonType
   256		Elem typeId
   257		Len  int
   258	}
   259	
   260	func newArrayType(name string) *arrayType {
   261		a := &arrayType{CommonType{Name: name}, 0, 0}
   262		return a
   263	}
   264	
   265	func (a *arrayType) init(elem gobType, len int) {
   266		// Set our type id before evaluating the element's, in case it's our own.
   267		setTypeId(a)
   268		a.Elem = elem.id()
   269		a.Len = len
   270	}
   271	
   272	func (a *arrayType) safeString(seen map[typeId]bool) string {
   273		if seen[a.Id] {
   274			return a.Name
   275		}
   276		seen[a.Id] = true
   277		return fmt.Sprintf("[%d]%s", a.Len, a.Elem.gobType().safeString(seen))
   278	}
   279	
   280	func (a *arrayType) string() string { return a.safeString(make(map[typeId]bool)) }
   281	
   282	// GobEncoder type (something that implements the GobEncoder interface)
   283	type gobEncoderType struct {
   284		CommonType
   285	}
   286	
   287	func newGobEncoderType(name string) *gobEncoderType {
   288		g := &gobEncoderType{CommonType{Name: name}}
   289		setTypeId(g)
   290		return g
   291	}
   292	
   293	func (g *gobEncoderType) safeString(seen map[typeId]bool) string {
   294		return g.Name
   295	}
   296	
   297	func (g *gobEncoderType) string() string { return g.Name }
   298	
   299	// Map type
   300	type mapType struct {
   301		CommonType
   302		Key  typeId
   303		Elem typeId
   304	}
   305	
   306	func newMapType(name string) *mapType {
   307		m := &mapType{CommonType{Name: name}, 0, 0}
   308		return m
   309	}
   310	
   311	func (m *mapType) init(key, elem gobType) {
   312		// Set our type id before evaluating the element's, in case it's our own.
   313		setTypeId(m)
   314		m.Key = key.id()
   315		m.Elem = elem.id()
   316	}
   317	
   318	func (m *mapType) safeString(seen map[typeId]bool) string {
   319		if seen[m.Id] {
   320			return m.Name
   321		}
   322		seen[m.Id] = true
   323		key := m.Key.gobType().safeString(seen)
   324		elem := m.Elem.gobType().safeString(seen)
   325		return fmt.Sprintf("map[%s]%s", key, elem)
   326	}
   327	
   328	func (m *mapType) string() string { return m.safeString(make(map[typeId]bool)) }
   329	
   330	// Slice type
   331	type sliceType struct {
   332		CommonType
   333		Elem typeId
   334	}
   335	
   336	func newSliceType(name string) *sliceType {
   337		s := &sliceType{CommonType{Name: name}, 0}
   338		return s
   339	}
   340	
   341	func (s *sliceType) init(elem gobType) {
   342		// Set our type id before evaluating the element's, in case it's our own.
   343		setTypeId(s)
   344		s.Elem = elem.id()
   345	}
   346	
   347	func (s *sliceType) safeString(seen map[typeId]bool) string {
   348		if seen[s.Id] {
   349			return s.Name
   350		}
   351		seen[s.Id] = true
   352		return fmt.Sprintf("[]%s", s.Elem.gobType().safeString(seen))
   353	}
   354	
   355	func (s *sliceType) string() string { return s.safeString(make(map[typeId]bool)) }
   356	
   357	// Struct type
   358	type fieldType struct {
   359		Name string
   360		Id   typeId
   361	}
   362	
   363	type structType struct {
   364		CommonType
   365		Field []*fieldType
   366	}
   367	
   368	func (s *structType) safeString(seen map[typeId]bool) string {
   369		if s == nil {
   370			return "<nil>"
   371		}
   372		if _, ok := seen[s.Id]; ok {
   373			return s.Name
   374		}
   375		seen[s.Id] = true
   376		str := s.Name + " = struct { "
   377		for _, f := range s.Field {
   378			str += fmt.Sprintf("%s %s; ", f.Name, f.Id.gobType().safeString(seen))
   379		}
   380		str += "}"
   381		return str
   382	}
   383	
   384	func (s *structType) string() string { return s.safeString(make(map[typeId]bool)) }
   385	
   386	func newStructType(name string) *structType {
   387		s := &structType{CommonType{Name: name}, nil}
   388		// For historical reasons we set the id here rather than init.
   389		// See the comment in newTypeObject for details.
   390		setTypeId(s)
   391		return s
   392	}
   393	
   394	// newTypeObject allocates a gobType for the reflection type rt.
   395	// Unless ut represents a GobEncoder, rt should be the base type
   396	// of ut.
   397	// This is only called from the encoding side. The decoding side
   398	// works through typeIds and userTypeInfos alone.
   399	func newTypeObject(name string, ut *userTypeInfo, rt reflect.Type) (gobType, os.Error) {
   400		// Does this type implement GobEncoder?
   401		if ut.isGobEncoder {
   402			return newGobEncoderType(name), nil
   403		}
   404		var err os.Error
   405		var type0, type1 gobType
   406		defer func() {
   407			if err != nil {
   408				types[rt] = nil, false
   409			}
   410		}()
   411		// Install the top-level type before the subtypes (e.g. struct before
   412		// fields) so recursive types can be constructed safely.
   413		switch t := rt; t.Kind() {
   414		// All basic types are easy: they are predefined.
   415		case reflect.Bool:
   416			return tBool.gobType(), nil
   417	
   418		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
   419			return tInt.gobType(), nil
   420	
   421		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
   422			return tUint.gobType(), nil
   423	
   424		case reflect.Float32, reflect.Float64:
   425			return tFloat.gobType(), nil
   426	
   427		case reflect.Complex64, reflect.Complex128:
   428			return tComplex.gobType(), nil
   429	
   430		case reflect.String:
   431			return tString.gobType(), nil
   432	
   433		case reflect.Interface:
   434			return tInterface.gobType(), nil
   435	
   436		case reflect.Array:
   437			at := newArrayType(name)
   438			types[rt] = at
   439			type0, err = getBaseType("", t.Elem())
   440			if err != nil {
   441				return nil, err
   442			}
   443			// Historical aside:
   444			// For arrays, maps, and slices, we set the type id after the elements
   445			// are constructed. This is to retain the order of type id allocation after
   446			// a fix made to handle recursive types, which changed the order in
   447			// which types are built.  Delaying the setting in this way preserves
   448			// type ids while allowing recursive types to be described. Structs,
   449			// done below, were already handling recursion correctly so they
   450			// assign the top-level id before those of the field.
   451			at.init(type0, t.Len())
   452			return at, nil
   453	
   454		case reflect.Map:
   455			mt := newMapType(name)
   456			types[rt] = mt
   457			type0, err = getBaseType("", t.Key())
   458			if err != nil {
   459				return nil, err
   460			}
   461			type1, err = getBaseType("", t.Elem())
   462			if err != nil {
   463				return nil, err
   464			}
   465			mt.init(type0, type1)
   466			return mt, nil
   467	
   468		case reflect.Slice:
   469			// []byte == []uint8 is a special case
   470			if t.Elem().Kind() == reflect.Uint8 {
   471				return tBytes.gobType(), nil
   472			}
   473			st := newSliceType(name)
   474			types[rt] = st
   475			type0, err = getBaseType(t.Elem().Name(), t.Elem())
   476			if err != nil {
   477				return nil, err
   478			}
   479			st.init(type0)
   480			return st, nil
   481	
   482		case reflect.Struct:
   483			st := newStructType(name)
   484			types[rt] = st
   485			idToType[st.id()] = st
   486			for i := 0; i < t.NumField(); i++ {
   487				f := t.Field(i)
   488				if !isExported(f.Name) {
   489					continue
   490				}
   491				typ := userType(f.Type).base
   492				tname := typ.Name()
   493				if tname == "" {
   494					t := userType(f.Type).base
   495					tname = t.String()
   496				}
   497				gt, err := getBaseType(tname, f.Type)
   498				if err != nil {
   499					return nil, err
   500				}
   501				st.Field = append(st.Field, &fieldType{f.Name, gt.id()})
   502			}
   503			return st, nil
   504	
   505		default:
   506			return nil, os.NewError("gob NewTypeObject can't handle type: " + rt.String())
   507		}
   508		return nil, nil
   509	}
   510	
   511	// isExported reports whether this is an exported - upper case - name.
   512	func isExported(name string) bool {
   513		rune, _ := utf8.DecodeRuneInString(name)
   514		return unicode.IsUpper(rune)
   515	}
   516	
   517	// getBaseType returns the Gob type describing the given reflect.Type's base type.
   518	// typeLock must be held.
   519	func getBaseType(name string, rt reflect.Type) (gobType, os.Error) {
   520		ut := userType(rt)
   521		return getType(name, ut, ut.base)
   522	}
   523	
   524	// getType returns the Gob type describing the given reflect.Type.
   525	// Should be called only when handling GobEncoders/Decoders,
   526	// which may be pointers.  All other types are handled through the
   527	// base type, never a pointer.
   528	// typeLock must be held.
   529	func getType(name string, ut *userTypeInfo, rt reflect.Type) (gobType, os.Error) {
   530		typ, present := types[rt]
   531		if present {
   532			return typ, nil
   533		}
   534		typ, err := newTypeObject(name, ut, rt)
   535		if err == nil {
   536			types[rt] = typ
   537		}
   538		return typ, err
   539	}
   540	
   541	func checkId(want, got typeId) {
   542		if want != got {
   543			fmt.Fprintf(os.Stderr, "checkId: %d should be %d\n", int(got), int(want))
   544			panic("bootstrap type wrong id: " + got.name() + " " + got.string() + " not " + want.string())
   545		}
   546	}
   547	
   548	// used for building the basic types; called only from init().  the incoming
   549	// interface always refers to a pointer.
   550	func bootstrapType(name string, e interface{}, expect typeId) typeId {
   551		rt := reflect.TypeOf(e).Elem()
   552		_, present := types[rt]
   553		if present {
   554			panic("bootstrap type already present: " + name + ", " + rt.String())
   555		}
   556		typ := &CommonType{Name: name}
   557		types[rt] = typ
   558		setTypeId(typ)
   559		checkId(expect, nextId)
   560		userType(rt) // might as well cache it now
   561		return nextId
   562	}
   563	
   564	// Representation of the information we send and receive about this type.
   565	// Each value we send is preceded by its type definition: an encoded int.
   566	// However, the very first time we send the value, we first send the pair
   567	// (-id, wireType).
   568	// For bootstrapping purposes, we assume that the recipient knows how
   569	// to decode a wireType; it is exactly the wireType struct here, interpreted
   570	// using the gob rules for sending a structure, except that we assume the
   571	// ids for wireType and structType etc. are known.  The relevant pieces
   572	// are built in encode.go's init() function.
   573	// To maintain binary compatibility, if you extend this type, always put
   574	// the new fields last.
   575	type wireType struct {
   576		ArrayT      *arrayType
   577		SliceT      *sliceType
   578		StructT     *structType
   579		MapT        *mapType
   580		GobEncoderT *gobEncoderType
   581	}
   582	
   583	func (w *wireType) string() string {
   584		const unknown = "unknown type"
   585		if w == nil {
   586			return unknown
   587		}
   588		switch {
   589		case w.ArrayT != nil:
   590			return w.ArrayT.Name
   591		case w.SliceT != nil:
   592			return w.SliceT.Name
   593		case w.StructT != nil:
   594			return w.StructT.Name
   595		case w.MapT != nil:
   596			return w.MapT.Name
   597		case w.GobEncoderT != nil:
   598			return w.GobEncoderT.Name
   599		}
   600		return unknown
   601	}
   602	
   603	type typeInfo struct {
   604		id      typeId
   605		encoder *encEngine
   606		wire    *wireType
   607	}
   608	
   609	var typeInfoMap = make(map[reflect.Type]*typeInfo) // protected by typeLock
   610	
   611	// typeLock must be held.
   612	func getTypeInfo(ut *userTypeInfo) (*typeInfo, os.Error) {
   613		rt := ut.base
   614		if ut.isGobEncoder {
   615			// We want the user type, not the base type.
   616			rt = ut.user
   617		}
   618		info, ok := typeInfoMap[rt]
   619		if ok {
   620			return info, nil
   621		}
   622		info = new(typeInfo)
   623		gt, err := getBaseType(rt.Name(), rt)
   624		if err != nil {
   625			return nil, err
   626		}
   627		info.id = gt.id()
   628	
   629		if ut.isGobEncoder {
   630			userType, err := getType(rt.Name(), ut, rt)
   631			if err != nil {
   632				return nil, err
   633			}
   634			info.wire = &wireType{GobEncoderT: userType.id().gobType().(*gobEncoderType)}
   635			typeInfoMap[ut.user] = info
   636			return info, nil
   637		}
   638	
   639		t := info.id.gobType()
   640		switch typ := rt; typ.Kind() {
   641		case reflect.Array:
   642			info.wire = &wireType{ArrayT: t.(*arrayType)}
   643		case reflect.Map:
   644			info.wire = &wireType{MapT: t.(*mapType)}
   645		case reflect.Slice:
   646			// []byte == []uint8 is a special case handled separately
   647			if typ.Elem().Kind() != reflect.Uint8 {
   648				info.wire = &wireType{SliceT: t.(*sliceType)}
   649			}
   650		case reflect.Struct:
   651			info.wire = &wireType{StructT: t.(*structType)}
   652		}
   653		typeInfoMap[rt] = info
   654		return info, nil
   655	}
   656	
   657	// Called only when a panic is acceptable and unexpected.
   658	func mustGetTypeInfo(rt reflect.Type) *typeInfo {
   659		t, err := getTypeInfo(userType(rt))
   660		if err != nil {
   661			panic("getTypeInfo: " + err.String())
   662		}
   663		return t
   664	}
   665	
   666	// GobEncoder is the interface describing data that provides its own
   667	// representation for encoding values for transmission to a GobDecoder.
   668	// A type that implements GobEncoder and GobDecoder has complete
   669	// control over the representation of its data and may therefore
   670	// contain things such as private fields, channels, and functions,
   671	// which are not usually transmissible in gob streams.
   672	//
   673	// Note: Since gobs can be stored permanently, It is good design
   674	// to guarantee the encoding used by a GobEncoder is stable as the
   675	// software evolves.  For instance, it might make sense for GobEncode
   676	// to include a version number in the encoding.
   677	type GobEncoder interface {
   678		// GobEncode returns a byte slice representing the encoding of the
   679		// receiver for transmission to a GobDecoder, usually of the same
   680		// concrete type.
   681		GobEncode() ([]byte, os.Error)
   682	}
   683	
   684	// GobDecoder is the interface describing data that provides its own
   685	// routine for decoding transmitted values sent by a GobEncoder.
   686	type GobDecoder interface {
   687		// GobDecode overwrites the receiver, which must be a pointer,
   688		// with the value represented by the byte slice, which was written
   689		// by GobEncode, usually for the same concrete type.
   690		GobDecode([]byte) os.Error
   691	}
   692	
   693	var (
   694		nameToConcreteType = make(map[string]reflect.Type)
   695		concreteTypeToName = make(map[reflect.Type]string)
   696	)
   697	
   698	// RegisterName is like Register but uses the provided name rather than the
   699	// type's default.
   700	func RegisterName(name string, value interface{}) {
   701		if name == "" {
   702			// reserved for nil
   703			panic("attempt to register empty name")
   704		}
   705		base := userType(reflect.TypeOf(value)).base
   706		// Check for incompatible duplicates.
   707		if t, ok := nameToConcreteType[name]; ok && t != base {
   708			panic("gob: registering duplicate types for " + name)
   709		}
   710		if n, ok := concreteTypeToName[base]; ok && n != name {
   711			panic("gob: registering duplicate names for " + base.String())
   712		}
   713		// Store the name and type provided by the user....
   714		nameToConcreteType[name] = reflect.TypeOf(value)
   715		// but the flattened type in the type table, since that's what decode needs.
   716		concreteTypeToName[base] = name
   717	}
   718	
   719	// Register records a type, identified by a value for that type, under its
   720	// internal type name.  That name will identify the concrete type of a value
   721	// sent or received as an interface variable.  Only types that will be
   722	// transferred as implementations of interface values need to be registered.
   723	// Expecting to be used only during initialization, it panics if the mapping
   724	// between types and names is not a bijection.
   725	func Register(value interface{}) {
   726		// Default to printed representation for unnamed types
   727		rt := reflect.TypeOf(value)
   728		name := rt.String()
   729	
   730		// But for named types (or pointers to them), qualify with import path.
   731		// Dereference one pointer looking for a named type.
   732		star := ""
   733		if rt.Name() == "" {
   734			if pt := rt; pt.Kind() == reflect.Ptr {
   735				star = "*"
   736				rt = pt
   737			}
   738		}
   739		if rt.Name() != "" {
   740			if rt.PkgPath() == "" {
   741				name = star + rt.Name()
   742			} else {
   743				name = star + rt.PkgPath() + "." + rt.Name()
   744			}
   745		}
   746	
   747		RegisterName(name, value)
   748	}
   749	
   750	func registerBasics() {
   751		Register(int(0))
   752		Register(int8(0))
   753		Register(int16(0))
   754		Register(int32(0))
   755		Register(int64(0))
   756		Register(uint(0))
   757		Register(uint8(0))
   758		Register(uint16(0))
   759		Register(uint32(0))
   760		Register(uint64(0))
   761		Register(float32(0))
   762		Register(float64(0))
   763		Register(complex64(0i))
   764		Register(complex128(0i))
   765		Register(uintptr(0))
   766		Register(false)
   767		Register("")
   768		Register([]byte(nil))
   769		Register([]int(nil))
   770		Register([]int8(nil))
   771		Register([]int16(nil))
   772		Register([]int32(nil))
   773		Register([]int64(nil))
   774		Register([]uint(nil))
   775		Register([]uint8(nil))
   776		Register([]uint16(nil))
   777		Register([]uint32(nil))
   778		Register([]uint64(nil))
   779		Register([]float32(nil))
   780		Register([]float64(nil))
   781		Register([]complex64(nil))
   782		Register([]complex128(nil))
   783		Register([]uintptr(nil))
   784		Register([]bool(nil))
   785		Register([]string(nil))
   786	}

release.r60.3. Except as noted, this content is licensed under a Creative Commons Attribution 3.0 License.