Source file src/internal/abi/type.go

     1  // Copyright 2023 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 abi
     6  
     7  import (
     8  	"unsafe"
     9  )
    10  
    11  // Type is the runtime representation of a Go type.
    12  //
    13  // Be careful about accessing this type at build time, as the version
    14  // of this type in the compiler/linker may not have the same layout
    15  // as the version in the target binary, due to pointer width
    16  // differences and any experiments. Use cmd/compile/internal/rttype
    17  // or the functions in compiletype.go to access this type instead.
    18  // (TODO: this admonition applies to every type in this package.
    19  // Put it in some shared location?)
    20  type Type struct {
    21  	Size_       uintptr
    22  	PtrBytes    uintptr // number of (prefix) bytes in the type that can contain pointers
    23  	Hash        uint32  // hash of type; avoids computation in hash tables
    24  	TFlag       TFlag   // extra type information flags
    25  	Align_      uint8   // alignment of variable with this type
    26  	FieldAlign_ uint8   // alignment of struct field with this type
    27  	Kind_       uint8   // enumeration for C
    28  	// function for comparing objects of this type
    29  	// (ptr to object A, ptr to object B) -> ==?
    30  	Equal func(unsafe.Pointer, unsafe.Pointer) bool
    31  	// GCData stores the GC type data for the garbage collector.
    32  	// If the KindGCProg bit is set in kind, GCData is a GC program.
    33  	// Otherwise it is a ptrmask bitmap. See mbitmap.go for details.
    34  	GCData    *byte
    35  	Str       NameOff // string form
    36  	PtrToThis TypeOff // type for pointer to this type, may be zero
    37  }
    38  
    39  // A Kind represents the specific kind of type that a Type represents.
    40  // The zero Kind is not a valid kind.
    41  type Kind uint
    42  
    43  const (
    44  	Invalid Kind = iota
    45  	Bool
    46  	Int
    47  	Int8
    48  	Int16
    49  	Int32
    50  	Int64
    51  	Uint
    52  	Uint8
    53  	Uint16
    54  	Uint32
    55  	Uint64
    56  	Uintptr
    57  	Float32
    58  	Float64
    59  	Complex64
    60  	Complex128
    61  	Array
    62  	Chan
    63  	Func
    64  	Interface
    65  	Map
    66  	Pointer
    67  	Slice
    68  	String
    69  	Struct
    70  	UnsafePointer
    71  )
    72  
    73  const (
    74  	// TODO (khr, drchase) why aren't these in TFlag?  Investigate, fix if possible.
    75  	KindDirectIface = 1 << 5
    76  	KindGCProg      = 1 << 6 // Type.gc points to GC program
    77  	KindMask        = (1 << 5) - 1
    78  )
    79  
    80  // TFlag is used by a Type to signal what extra type information is
    81  // available in the memory directly following the Type value.
    82  type TFlag uint8
    83  
    84  const (
    85  	// TFlagUncommon means that there is a data with a type, UncommonType,
    86  	// just beyond the shared-per-type common data.  That is, the data
    87  	// for struct types will store their UncommonType at one offset, the
    88  	// data for interface types will store their UncommonType at a different
    89  	// offset.  UncommonType is always accessed via a pointer that is computed
    90  	// using trust-us-we-are-the-implementors pointer arithmetic.
    91  	//
    92  	// For example, if t.Kind() == Struct and t.tflag&TFlagUncommon != 0,
    93  	// then t has UncommonType data and it can be accessed as:
    94  	//
    95  	//	type structTypeUncommon struct {
    96  	//		structType
    97  	//		u UncommonType
    98  	//	}
    99  	//	u := &(*structTypeUncommon)(unsafe.Pointer(t)).u
   100  	TFlagUncommon TFlag = 1 << 0
   101  
   102  	// TFlagExtraStar means the name in the str field has an
   103  	// extraneous '*' prefix. This is because for most types T in
   104  	// a program, the type *T also exists and reusing the str data
   105  	// saves binary size.
   106  	TFlagExtraStar TFlag = 1 << 1
   107  
   108  	// TFlagNamed means the type has a name.
   109  	TFlagNamed TFlag = 1 << 2
   110  
   111  	// TFlagRegularMemory means that equal and hash functions can treat
   112  	// this type as a single region of t.size bytes.
   113  	TFlagRegularMemory TFlag = 1 << 3
   114  
   115  	// TFlagUnrolledBitmap marks special types that are unrolled-bitmap
   116  	// versions of types with GC programs.
   117  	// These types need to be deallocated when the underlying object
   118  	// is freed.
   119  	TFlagUnrolledBitmap TFlag = 1 << 4
   120  )
   121  
   122  // NameOff is the offset to a name from moduledata.types.  See resolveNameOff in runtime.
   123  type NameOff int32
   124  
   125  // TypeOff is the offset to a type from moduledata.types.  See resolveTypeOff in runtime.
   126  type TypeOff int32
   127  
   128  // TextOff is an offset from the top of a text section.  See (rtype).textOff in runtime.
   129  type TextOff int32
   130  
   131  // String returns the name of k.
   132  func (k Kind) String() string {
   133  	if int(k) < len(kindNames) {
   134  		return kindNames[k]
   135  	}
   136  	return kindNames[0]
   137  }
   138  
   139  var kindNames = []string{
   140  	Invalid:       "invalid",
   141  	Bool:          "bool",
   142  	Int:           "int",
   143  	Int8:          "int8",
   144  	Int16:         "int16",
   145  	Int32:         "int32",
   146  	Int64:         "int64",
   147  	Uint:          "uint",
   148  	Uint8:         "uint8",
   149  	Uint16:        "uint16",
   150  	Uint32:        "uint32",
   151  	Uint64:        "uint64",
   152  	Uintptr:       "uintptr",
   153  	Float32:       "float32",
   154  	Float64:       "float64",
   155  	Complex64:     "complex64",
   156  	Complex128:    "complex128",
   157  	Array:         "array",
   158  	Chan:          "chan",
   159  	Func:          "func",
   160  	Interface:     "interface",
   161  	Map:           "map",
   162  	Pointer:       "ptr",
   163  	Slice:         "slice",
   164  	String:        "string",
   165  	Struct:        "struct",
   166  	UnsafePointer: "unsafe.Pointer",
   167  }
   168  
   169  func (t *Type) Kind() Kind { return Kind(t.Kind_ & KindMask) }
   170  
   171  func (t *Type) HasName() bool {
   172  	return t.TFlag&TFlagNamed != 0
   173  }
   174  
   175  func (t *Type) Pointers() bool { return t.PtrBytes != 0 }
   176  
   177  // IfaceIndir reports whether t is stored indirectly in an interface value.
   178  func (t *Type) IfaceIndir() bool {
   179  	return t.Kind_&KindDirectIface == 0
   180  }
   181  
   182  // isDirectIface reports whether t is stored directly in an interface value.
   183  func (t *Type) IsDirectIface() bool {
   184  	return t.Kind_&KindDirectIface != 0
   185  }
   186  
   187  func (t *Type) GcSlice(begin, end uintptr) []byte {
   188  	return unsafe.Slice(t.GCData, int(end))[begin:]
   189  }
   190  
   191  // Method on non-interface type
   192  type Method struct {
   193  	Name NameOff // name of method
   194  	Mtyp TypeOff // method type (without receiver)
   195  	Ifn  TextOff // fn used in interface call (one-word receiver)
   196  	Tfn  TextOff // fn used for normal method call
   197  }
   198  
   199  // UncommonType is present only for defined types or types with methods
   200  // (if T is a defined type, the uncommonTypes for T and *T have methods).
   201  // Using a pointer to this struct reduces the overall size required
   202  // to describe a non-defined type with no methods.
   203  type UncommonType struct {
   204  	PkgPath NameOff // import path; empty for built-in types like int, string
   205  	Mcount  uint16  // number of methods
   206  	Xcount  uint16  // number of exported methods
   207  	Moff    uint32  // offset from this uncommontype to [mcount]Method
   208  	_       uint32  // unused
   209  }
   210  
   211  func (t *UncommonType) Methods() []Method {
   212  	if t.Mcount == 0 {
   213  		return nil
   214  	}
   215  	return (*[1 << 16]Method)(addChecked(unsafe.Pointer(t), uintptr(t.Moff), "t.mcount > 0"))[:t.Mcount:t.Mcount]
   216  }
   217  
   218  func (t *UncommonType) ExportedMethods() []Method {
   219  	if t.Xcount == 0 {
   220  		return nil
   221  	}
   222  	return (*[1 << 16]Method)(addChecked(unsafe.Pointer(t), uintptr(t.Moff), "t.xcount > 0"))[:t.Xcount:t.Xcount]
   223  }
   224  
   225  // addChecked returns p+x.
   226  //
   227  // The whySafe string is ignored, so that the function still inlines
   228  // as efficiently as p+x, but all call sites should use the string to
   229  // record why the addition is safe, which is to say why the addition
   230  // does not cause x to advance to the very end of p's allocation
   231  // and therefore point incorrectly at the next block in memory.
   232  func addChecked(p unsafe.Pointer, x uintptr, whySafe string) unsafe.Pointer {
   233  	return unsafe.Pointer(uintptr(p) + x)
   234  }
   235  
   236  // Imethod represents a method on an interface type
   237  type Imethod struct {
   238  	Name NameOff // name of method
   239  	Typ  TypeOff // .(*FuncType) underneath
   240  }
   241  
   242  // ArrayType represents a fixed array type.
   243  type ArrayType struct {
   244  	Type
   245  	Elem  *Type // array element type
   246  	Slice *Type // slice type
   247  	Len   uintptr
   248  }
   249  
   250  // Len returns the length of t if t is an array type, otherwise 0
   251  func (t *Type) Len() int {
   252  	if t.Kind() == Array {
   253  		return int((*ArrayType)(unsafe.Pointer(t)).Len)
   254  	}
   255  	return 0
   256  }
   257  
   258  func (t *Type) Common() *Type {
   259  	return t
   260  }
   261  
   262  type ChanDir int
   263  
   264  const (
   265  	RecvDir    ChanDir = 1 << iota         // <-chan
   266  	SendDir                                // chan<-
   267  	BothDir            = RecvDir | SendDir // chan
   268  	InvalidDir ChanDir = 0
   269  )
   270  
   271  // ChanType represents a channel type
   272  type ChanType struct {
   273  	Type
   274  	Elem *Type
   275  	Dir  ChanDir
   276  }
   277  
   278  type structTypeUncommon struct {
   279  	StructType
   280  	u UncommonType
   281  }
   282  
   283  // ChanDir returns the direction of t if t is a channel type, otherwise InvalidDir (0).
   284  func (t *Type) ChanDir() ChanDir {
   285  	if t.Kind() == Chan {
   286  		ch := (*ChanType)(unsafe.Pointer(t))
   287  		return ch.Dir
   288  	}
   289  	return InvalidDir
   290  }
   291  
   292  // Uncommon returns a pointer to T's "uncommon" data if there is any, otherwise nil
   293  func (t *Type) Uncommon() *UncommonType {
   294  	if t.TFlag&TFlagUncommon == 0 {
   295  		return nil
   296  	}
   297  	switch t.Kind() {
   298  	case Struct:
   299  		return &(*structTypeUncommon)(unsafe.Pointer(t)).u
   300  	case Pointer:
   301  		type u struct {
   302  			PtrType
   303  			u UncommonType
   304  		}
   305  		return &(*u)(unsafe.Pointer(t)).u
   306  	case Func:
   307  		type u struct {
   308  			FuncType
   309  			u UncommonType
   310  		}
   311  		return &(*u)(unsafe.Pointer(t)).u
   312  	case Slice:
   313  		type u struct {
   314  			SliceType
   315  			u UncommonType
   316  		}
   317  		return &(*u)(unsafe.Pointer(t)).u
   318  	case Array:
   319  		type u struct {
   320  			ArrayType
   321  			u UncommonType
   322  		}
   323  		return &(*u)(unsafe.Pointer(t)).u
   324  	case Chan:
   325  		type u struct {
   326  			ChanType
   327  			u UncommonType
   328  		}
   329  		return &(*u)(unsafe.Pointer(t)).u
   330  	case Map:
   331  		type u struct {
   332  			MapType
   333  			u UncommonType
   334  		}
   335  		return &(*u)(unsafe.Pointer(t)).u
   336  	case Interface:
   337  		type u struct {
   338  			InterfaceType
   339  			u UncommonType
   340  		}
   341  		return &(*u)(unsafe.Pointer(t)).u
   342  	default:
   343  		type u struct {
   344  			Type
   345  			u UncommonType
   346  		}
   347  		return &(*u)(unsafe.Pointer(t)).u
   348  	}
   349  }
   350  
   351  // Elem returns the element type for t if t is an array, channel, map, pointer, or slice, otherwise nil.
   352  func (t *Type) Elem() *Type {
   353  	switch t.Kind() {
   354  	case Array:
   355  		tt := (*ArrayType)(unsafe.Pointer(t))
   356  		return tt.Elem
   357  	case Chan:
   358  		tt := (*ChanType)(unsafe.Pointer(t))
   359  		return tt.Elem
   360  	case Map:
   361  		tt := (*MapType)(unsafe.Pointer(t))
   362  		return tt.Elem
   363  	case Pointer:
   364  		tt := (*PtrType)(unsafe.Pointer(t))
   365  		return tt.Elem
   366  	case Slice:
   367  		tt := (*SliceType)(unsafe.Pointer(t))
   368  		return tt.Elem
   369  	}
   370  	return nil
   371  }
   372  
   373  // StructType returns t cast to a *StructType, or nil if its tag does not match.
   374  func (t *Type) StructType() *StructType {
   375  	if t.Kind() != Struct {
   376  		return nil
   377  	}
   378  	return (*StructType)(unsafe.Pointer(t))
   379  }
   380  
   381  // MapType returns t cast to a *MapType, or nil if its tag does not match.
   382  func (t *Type) MapType() *MapType {
   383  	if t.Kind() != Map {
   384  		return nil
   385  	}
   386  	return (*MapType)(unsafe.Pointer(t))
   387  }
   388  
   389  // ArrayType returns t cast to a *ArrayType, or nil if its tag does not match.
   390  func (t *Type) ArrayType() *ArrayType {
   391  	if t.Kind() != Array {
   392  		return nil
   393  	}
   394  	return (*ArrayType)(unsafe.Pointer(t))
   395  }
   396  
   397  // FuncType returns t cast to a *FuncType, or nil if its tag does not match.
   398  func (t *Type) FuncType() *FuncType {
   399  	if t.Kind() != Func {
   400  		return nil
   401  	}
   402  	return (*FuncType)(unsafe.Pointer(t))
   403  }
   404  
   405  // InterfaceType returns t cast to a *InterfaceType, or nil if its tag does not match.
   406  func (t *Type) InterfaceType() *InterfaceType {
   407  	if t.Kind() != Interface {
   408  		return nil
   409  	}
   410  	return (*InterfaceType)(unsafe.Pointer(t))
   411  }
   412  
   413  // Size returns the size of data with type t.
   414  func (t *Type) Size() uintptr { return t.Size_ }
   415  
   416  // Align returns the alignment of data with type t.
   417  func (t *Type) Align() int { return int(t.Align_) }
   418  
   419  func (t *Type) FieldAlign() int { return int(t.FieldAlign_) }
   420  
   421  type InterfaceType struct {
   422  	Type
   423  	PkgPath Name      // import path
   424  	Methods []Imethod // sorted by hash
   425  }
   426  
   427  func (t *Type) ExportedMethods() []Method {
   428  	ut := t.Uncommon()
   429  	if ut == nil {
   430  		return nil
   431  	}
   432  	return ut.ExportedMethods()
   433  }
   434  
   435  func (t *Type) NumMethod() int {
   436  	if t.Kind() == Interface {
   437  		tt := (*InterfaceType)(unsafe.Pointer(t))
   438  		return tt.NumMethod()
   439  	}
   440  	return len(t.ExportedMethods())
   441  }
   442  
   443  // NumMethod returns the number of interface methods in the type's method set.
   444  func (t *InterfaceType) NumMethod() int { return len(t.Methods) }
   445  
   446  type MapType struct {
   447  	Type
   448  	Key    *Type
   449  	Elem   *Type
   450  	Bucket *Type // internal type representing a hash bucket
   451  	// function for hashing keys (ptr to key, seed) -> hash
   452  	Hasher     func(unsafe.Pointer, uintptr) uintptr
   453  	KeySize    uint8  // size of key slot
   454  	ValueSize  uint8  // size of elem slot
   455  	BucketSize uint16 // size of bucket
   456  	Flags      uint32
   457  }
   458  
   459  // Note: flag values must match those used in the TMAP case
   460  // in ../cmd/compile/internal/reflectdata/reflect.go:writeType.
   461  func (mt *MapType) IndirectKey() bool { // store ptr to key instead of key itself
   462  	return mt.Flags&1 != 0
   463  }
   464  func (mt *MapType) IndirectElem() bool { // store ptr to elem instead of elem itself
   465  	return mt.Flags&2 != 0
   466  }
   467  func (mt *MapType) ReflexiveKey() bool { // true if k==k for all keys
   468  	return mt.Flags&4 != 0
   469  }
   470  func (mt *MapType) NeedKeyUpdate() bool { // true if we need to update key on an overwrite
   471  	return mt.Flags&8 != 0
   472  }
   473  func (mt *MapType) HashMightPanic() bool { // true if hash function might panic
   474  	return mt.Flags&16 != 0
   475  }
   476  
   477  func (t *Type) Key() *Type {
   478  	if t.Kind() == Map {
   479  		return (*MapType)(unsafe.Pointer(t)).Key
   480  	}
   481  	return nil
   482  }
   483  
   484  type SliceType struct {
   485  	Type
   486  	Elem *Type // slice element type
   487  }
   488  
   489  // funcType represents a function type.
   490  //
   491  // A *Type for each in and out parameter is stored in an array that
   492  // directly follows the funcType (and possibly its uncommonType). So
   493  // a function type with one method, one input, and one output is:
   494  //
   495  //	struct {
   496  //		funcType
   497  //		uncommonType
   498  //		[2]*rtype    // [0] is in, [1] is out
   499  //	}
   500  type FuncType struct {
   501  	Type
   502  	InCount  uint16
   503  	OutCount uint16 // top bit is set if last input parameter is ...
   504  }
   505  
   506  func (t *FuncType) In(i int) *Type {
   507  	return t.InSlice()[i]
   508  }
   509  
   510  func (t *FuncType) NumIn() int {
   511  	return int(t.InCount)
   512  }
   513  
   514  func (t *FuncType) NumOut() int {
   515  	return int(t.OutCount & (1<<15 - 1))
   516  }
   517  
   518  func (t *FuncType) Out(i int) *Type {
   519  	return (t.OutSlice()[i])
   520  }
   521  
   522  func (t *FuncType) InSlice() []*Type {
   523  	uadd := unsafe.Sizeof(*t)
   524  	if t.TFlag&TFlagUncommon != 0 {
   525  		uadd += unsafe.Sizeof(UncommonType{})
   526  	}
   527  	if t.InCount == 0 {
   528  		return nil
   529  	}
   530  	return (*[1 << 16]*Type)(addChecked(unsafe.Pointer(t), uadd, "t.inCount > 0"))[:t.InCount:t.InCount]
   531  }
   532  func (t *FuncType) OutSlice() []*Type {
   533  	outCount := uint16(t.NumOut())
   534  	if outCount == 0 {
   535  		return nil
   536  	}
   537  	uadd := unsafe.Sizeof(*t)
   538  	if t.TFlag&TFlagUncommon != 0 {
   539  		uadd += unsafe.Sizeof(UncommonType{})
   540  	}
   541  	return (*[1 << 17]*Type)(addChecked(unsafe.Pointer(t), uadd, "outCount > 0"))[t.InCount : t.InCount+outCount : t.InCount+outCount]
   542  }
   543  
   544  func (t *FuncType) IsVariadic() bool {
   545  	return t.OutCount&(1<<15) != 0
   546  }
   547  
   548  type PtrType struct {
   549  	Type
   550  	Elem *Type // pointer element (pointed at) type
   551  }
   552  
   553  type StructField struct {
   554  	Name   Name    // name is always non-empty
   555  	Typ    *Type   // type of field
   556  	Offset uintptr // byte offset of field
   557  }
   558  
   559  func (f *StructField) Embedded() bool {
   560  	return f.Name.IsEmbedded()
   561  }
   562  
   563  type StructType struct {
   564  	Type
   565  	PkgPath Name
   566  	Fields  []StructField
   567  }
   568  
   569  // Name is an encoded type Name with optional extra data.
   570  //
   571  // The first byte is a bit field containing:
   572  //
   573  //	1<<0 the name is exported
   574  //	1<<1 tag data follows the name
   575  //	1<<2 pkgPath nameOff follows the name and tag
   576  //	1<<3 the name is of an embedded (a.k.a. anonymous) field
   577  //
   578  // Following that, there is a varint-encoded length of the name,
   579  // followed by the name itself.
   580  //
   581  // If tag data is present, it also has a varint-encoded length
   582  // followed by the tag itself.
   583  //
   584  // If the import path follows, then 4 bytes at the end of
   585  // the data form a nameOff. The import path is only set for concrete
   586  // methods that are defined in a different package than their type.
   587  //
   588  // If a name starts with "*", then the exported bit represents
   589  // whether the pointed to type is exported.
   590  //
   591  // Note: this encoding must match here and in:
   592  //   cmd/compile/internal/reflectdata/reflect.go
   593  //   cmd/link/internal/ld/decodesym.go
   594  
   595  type Name struct {
   596  	Bytes *byte
   597  }
   598  
   599  // DataChecked does pointer arithmetic on n's Bytes, and that arithmetic is asserted to
   600  // be safe for the reason in whySafe (which can appear in a backtrace, etc.)
   601  func (n Name) DataChecked(off int, whySafe string) *byte {
   602  	return (*byte)(addChecked(unsafe.Pointer(n.Bytes), uintptr(off), whySafe))
   603  }
   604  
   605  // Data does pointer arithmetic on n's Bytes, and that arithmetic is asserted to
   606  // be safe because the runtime made the call (other packages use DataChecked)
   607  func (n Name) Data(off int) *byte {
   608  	return (*byte)(addChecked(unsafe.Pointer(n.Bytes), uintptr(off), "the runtime doesn't need to give you a reason"))
   609  }
   610  
   611  // IsExported returns "is n exported?"
   612  func (n Name) IsExported() bool {
   613  	return (*n.Bytes)&(1<<0) != 0
   614  }
   615  
   616  // HasTag returns true iff there is tag data following this name
   617  func (n Name) HasTag() bool {
   618  	return (*n.Bytes)&(1<<1) != 0
   619  }
   620  
   621  // IsEmbedded returns true iff n is embedded (an anonymous field).
   622  func (n Name) IsEmbedded() bool {
   623  	return (*n.Bytes)&(1<<3) != 0
   624  }
   625  
   626  // ReadVarint parses a varint as encoded by encoding/binary.
   627  // It returns the number of encoded bytes and the encoded value.
   628  func (n Name) ReadVarint(off int) (int, int) {
   629  	v := 0
   630  	for i := 0; ; i++ {
   631  		x := *n.DataChecked(off+i, "read varint")
   632  		v += int(x&0x7f) << (7 * i)
   633  		if x&0x80 == 0 {
   634  			return i + 1, v
   635  		}
   636  	}
   637  }
   638  
   639  // IsBlank indicates whether n is "_".
   640  func (n Name) IsBlank() bool {
   641  	if n.Bytes == nil {
   642  		return false
   643  	}
   644  	_, l := n.ReadVarint(1)
   645  	return l == 1 && *n.Data(2) == '_'
   646  }
   647  
   648  // writeVarint writes n to buf in varint form. Returns the
   649  // number of bytes written. n must be nonnegative.
   650  // Writes at most 10 bytes.
   651  func writeVarint(buf []byte, n int) int {
   652  	for i := 0; ; i++ {
   653  		b := byte(n & 0x7f)
   654  		n >>= 7
   655  		if n == 0 {
   656  			buf[i] = b
   657  			return i + 1
   658  		}
   659  		buf[i] = b | 0x80
   660  	}
   661  }
   662  
   663  // Name returns the tag string for n, or empty if there is none.
   664  func (n Name) Name() string {
   665  	if n.Bytes == nil {
   666  		return ""
   667  	}
   668  	i, l := n.ReadVarint(1)
   669  	return unsafe.String(n.DataChecked(1+i, "non-empty string"), l)
   670  }
   671  
   672  // Tag returns the tag string for n, or empty if there is none.
   673  func (n Name) Tag() string {
   674  	if !n.HasTag() {
   675  		return ""
   676  	}
   677  	i, l := n.ReadVarint(1)
   678  	i2, l2 := n.ReadVarint(1 + i + l)
   679  	return unsafe.String(n.DataChecked(1+i+l+i2, "non-empty string"), l2)
   680  }
   681  
   682  func NewName(n, tag string, exported, embedded bool) Name {
   683  	if len(n) >= 1<<29 {
   684  		panic("abi.NewName: name too long: " + n[:1024] + "...")
   685  	}
   686  	if len(tag) >= 1<<29 {
   687  		panic("abi.NewName: tag too long: " + tag[:1024] + "...")
   688  	}
   689  	var nameLen [10]byte
   690  	var tagLen [10]byte
   691  	nameLenLen := writeVarint(nameLen[:], len(n))
   692  	tagLenLen := writeVarint(tagLen[:], len(tag))
   693  
   694  	var bits byte
   695  	l := 1 + nameLenLen + len(n)
   696  	if exported {
   697  		bits |= 1 << 0
   698  	}
   699  	if len(tag) > 0 {
   700  		l += tagLenLen + len(tag)
   701  		bits |= 1 << 1
   702  	}
   703  	if embedded {
   704  		bits |= 1 << 3
   705  	}
   706  
   707  	b := make([]byte, l)
   708  	b[0] = bits
   709  	copy(b[1:], nameLen[:nameLenLen])
   710  	copy(b[1+nameLenLen:], n)
   711  	if len(tag) > 0 {
   712  		tb := b[1+nameLenLen+len(n):]
   713  		copy(tb, tagLen[:tagLenLen])
   714  		copy(tb[tagLenLen:], tag)
   715  	}
   716  
   717  	return Name{Bytes: &b[0]}
   718  }
   719  

View as plain text