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