Source file src/cmd/vendor/github.com/ianlancetaylor/demangle/rust.go

     1  // Copyright 2021 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 demangle
     6  
     7  import (
     8  	"fmt"
     9  	"math"
    10  	"math/bits"
    11  	"strings"
    12  	"unicode/utf8"
    13  )
    14  
    15  // rustToString demangles a Rust symbol.
    16  func rustToString(name string, options []Option) (ret string, err error) {
    17  	if !strings.HasPrefix(name, "_R") {
    18  		return "", ErrNotMangledName
    19  	}
    20  
    21  	// When the demangling routines encounter an error, they panic
    22  	// with a value of type demangleErr.
    23  	defer func() {
    24  		if r := recover(); r != nil {
    25  			if de, ok := r.(demangleErr); ok {
    26  				ret = ""
    27  				err = de
    28  				return
    29  			}
    30  			panic(r)
    31  		}
    32  	}()
    33  
    34  	suffix := ""
    35  	dot := strings.Index(name, ".")
    36  	if dot >= 0 {
    37  		suffix = name[dot:]
    38  		name = name[:dot]
    39  	}
    40  
    41  	name = name[2:]
    42  	rst := &rustState{orig: name, str: name}
    43  	rst.symbolName()
    44  
    45  	if len(rst.str) > 0 {
    46  		rst.fail("unparsed characters at end of mangled name")
    47  	}
    48  
    49  	if suffix != "" {
    50  		rst.skip = false
    51  		rst.writeString(" (")
    52  		rst.writeString(suffix)
    53  		rst.writeByte(')')
    54  	}
    55  
    56  	return rst.buf.String(), nil
    57  }
    58  
    59  // A rustState holds the current state of demangling a Rust string.
    60  type rustState struct {
    61  	orig      string          // the original string being demangled
    62  	str       string          // remainder of string to demangle
    63  	off       int             // offset of str within original string
    64  	buf       strings.Builder // demangled string being built
    65  	skip      bool            // don't print, just skip
    66  	lifetimes int64           // number of bound lifetimes
    67  	last      byte            // last byte written to buffer
    68  }
    69  
    70  // fail panics with demangleErr, to be caught in rustToString.
    71  func (rst *rustState) fail(err string) {
    72  	panic(demangleErr{err: err, off: rst.off})
    73  }
    74  
    75  // advance advances the current string offset.
    76  func (rst *rustState) advance(add int) {
    77  	if len(rst.str) < add {
    78  		panic("internal error")
    79  	}
    80  	rst.str = rst.str[add:]
    81  	rst.off += add
    82  }
    83  
    84  // checkChar requires that the next character in the string be c,
    85  // and advances past it.
    86  func (rst *rustState) checkChar(c byte) {
    87  	if len(rst.str) == 0 || rst.str[0] != c {
    88  		rst.fail("expected " + string(c))
    89  	}
    90  	rst.advance(1)
    91  }
    92  
    93  // writeByte writes a byte to the buffer.
    94  func (rst *rustState) writeByte(c byte) {
    95  	if rst.skip {
    96  		return
    97  	}
    98  	rst.last = c
    99  	rst.buf.WriteByte(c)
   100  }
   101  
   102  // writeString writes a string to the buffer.
   103  func (rst *rustState) writeString(s string) {
   104  	if rst.skip {
   105  		return
   106  	}
   107  	if len(s) > 0 {
   108  		rst.last = s[len(s)-1]
   109  		rst.buf.WriteString(s)
   110  	}
   111  }
   112  
   113  // <symbol-name> = "_R" [<decimal-number>] <path> [<instantiating-crate>]
   114  // <instantiating-crate> = <path>
   115  //
   116  // We've already skipped the "_R".
   117  func (rst *rustState) symbolName() {
   118  	if len(rst.str) < 1 {
   119  		rst.fail("expected symbol-name")
   120  	}
   121  
   122  	if isDigit(rst.str[0]) {
   123  		rst.fail("unsupported Rust encoding version")
   124  	}
   125  
   126  	rst.path(true)
   127  
   128  	if len(rst.str) > 0 {
   129  		rst.skip = true
   130  		rst.path(false)
   131  	}
   132  }
   133  
   134  // <path> = "C" <identifier>                    // crate root
   135  //        | "M" <impl-path> <type>              // <T> (inherent impl)
   136  //        | "X" <impl-path> <type> <path>       // <T as Trait> (trait impl)
   137  //        | "Y" <type> <path>                   // <T as Trait> (trait definition)
   138  //        | "N" <namespace> <path> <identifier> // ...::ident (nested path)
   139  //        | "I" <path> {<generic-arg>} "E"      // ...<T, U> (generic args)
   140  //        | <backref>
   141  // <namespace> = "C"      // closure
   142  //             | "S"      // shim
   143  //             | <A-Z>    // other special namespaces
   144  //             | <a-z>    // internal namespaces
   145  //
   146  // needsSeparator is true if we need to write out :: for a generic;
   147  // it is passed as false if we are in the middle of a type.
   148  func (rst *rustState) path(needsSeparator bool) {
   149  	if len(rst.str) < 1 {
   150  		rst.fail("expected path")
   151  	}
   152  	switch c := rst.str[0]; c {
   153  	case 'C':
   154  		rst.advance(1)
   155  		_, ident := rst.identifier()
   156  		rst.writeString(ident)
   157  	case 'M', 'X':
   158  		rst.advance(1)
   159  		rst.implPath()
   160  		rst.writeByte('<')
   161  		rst.demangleType()
   162  		if c == 'X' {
   163  			rst.writeString(" as ")
   164  			rst.path(false)
   165  		}
   166  		rst.writeByte('>')
   167  	case 'Y':
   168  		rst.advance(1)
   169  		rst.writeByte('<')
   170  		rst.demangleType()
   171  		rst.writeString(" as ")
   172  		rst.path(false)
   173  		rst.writeByte('>')
   174  	case 'N':
   175  		rst.advance(1)
   176  
   177  		if len(rst.str) < 1 {
   178  			rst.fail("expected namespace")
   179  		}
   180  		ns := rst.str[0]
   181  		switch {
   182  		case ns >= 'a' && ns <= 'z':
   183  		case ns >= 'A' && ns <= 'Z':
   184  		default:
   185  			rst.fail("invalid namespace character")
   186  		}
   187  		rst.advance(1)
   188  
   189  		rst.path(needsSeparator)
   190  
   191  		dis, ident := rst.identifier()
   192  
   193  		if ns >= 'A' && ns <= 'Z' {
   194  			rst.writeString("::{")
   195  			switch ns {
   196  			case 'C':
   197  				rst.writeString("closure")
   198  			case 'S':
   199  				rst.writeString("shim")
   200  			default:
   201  				rst.writeByte(ns)
   202  			}
   203  			if len(ident) > 0 {
   204  				rst.writeByte(':')
   205  				rst.writeString(ident)
   206  			}
   207  			if !rst.skip {
   208  				fmt.Fprintf(&rst.buf, "#%d}", dis)
   209  				rst.last = '}'
   210  			}
   211  		} else {
   212  			rst.writeString("::")
   213  			rst.writeString(ident)
   214  		}
   215  	case 'I':
   216  		rst.advance(1)
   217  		rst.path(needsSeparator)
   218  		if needsSeparator {
   219  			rst.writeString("::")
   220  		}
   221  		rst.writeByte('<')
   222  		first := true
   223  		for len(rst.str) > 0 && rst.str[0] != 'E' {
   224  			if first {
   225  				first = false
   226  			} else {
   227  				rst.writeString(", ")
   228  			}
   229  			rst.genericArg()
   230  		}
   231  		rst.writeByte('>')
   232  		rst.checkChar('E')
   233  	case 'B':
   234  		rst.backref(func() { rst.path(needsSeparator) })
   235  	default:
   236  		rst.fail("unrecognized letter in path")
   237  	}
   238  }
   239  
   240  // <impl-path> = [<disambiguator>] <path>
   241  func (rst *rustState) implPath() {
   242  	// This path is not part of the demangled string.
   243  	hold := rst.skip
   244  	rst.skip = true
   245  	defer func() {
   246  		rst.skip = hold
   247  	}()
   248  
   249  	rst.disambiguator()
   250  	rst.path(false)
   251  }
   252  
   253  // <identifier> = [<disambiguator>] <undisambiguated-identifier>
   254  // Returns the disambiguator and the identifier.
   255  func (rst *rustState) identifier() (int64, string) {
   256  	dis := rst.disambiguator()
   257  	ident := rst.undisambiguatedIdentifier()
   258  	return dis, ident
   259  }
   260  
   261  // <disambiguator> = "s" <base-62-number>
   262  // This is optional.
   263  func (rst *rustState) disambiguator() int64 {
   264  	if len(rst.str) == 0 || rst.str[0] != 's' {
   265  		return 0
   266  	}
   267  	rst.advance(1)
   268  	return rst.base62Number() + 1
   269  }
   270  
   271  // <undisambiguated-identifier> = ["u"] <decimal-number> ["_"] <bytes>
   272  func (rst *rustState) undisambiguatedIdentifier() string {
   273  	punycode := false
   274  	if len(rst.str) > 0 && rst.str[0] == 'u' {
   275  		rst.advance(1)
   276  		punycode = true
   277  	}
   278  
   279  	val := rst.decimalNumber()
   280  
   281  	if len(rst.str) > 0 && rst.str[0] == '_' {
   282  		rst.advance(1)
   283  	}
   284  
   285  	if len(rst.str) < val {
   286  		rst.fail("not enough characters for identifier")
   287  	}
   288  	id := rst.str[:val]
   289  	rst.advance(val)
   290  
   291  	for i := 0; i < len(id); i++ {
   292  		c := id[i]
   293  		switch {
   294  		case c >= '0' && c <= '9':
   295  		case c >= 'A' && c <= 'Z':
   296  		case c >= 'a' && c <= 'z':
   297  		case c == '_':
   298  		default:
   299  			rst.fail("invalid character in identifier")
   300  		}
   301  	}
   302  
   303  	if punycode {
   304  		id = rst.expandPunycode(id)
   305  	}
   306  
   307  	return id
   308  }
   309  
   310  // expandPunycode decodes the Rust version of punycode.
   311  // This algorithm is taken from RFC 3492 section 6.2.
   312  func (rst *rustState) expandPunycode(s string) string {
   313  	const (
   314  		base        = 36
   315  		tmin        = 1
   316  		tmax        = 26
   317  		skew        = 38
   318  		damp        = 700
   319  		initialBias = 72
   320  		initialN    = 128
   321  	)
   322  
   323  	idx := strings.LastIndex(s, "_")
   324  	if idx < 0 {
   325  		rst.fail("missing underscore in punycode string")
   326  	}
   327  
   328  	output := []rune(s[:idx])
   329  	encoding := s[idx+1:]
   330  
   331  	i := 0
   332  	n := initialN
   333  	bias := initialBias
   334  
   335  	pos := 0
   336  	for pos < len(encoding) {
   337  		oldI := i
   338  		w := 1
   339  		for k := base; ; k += base {
   340  			if pos == len(encoding) {
   341  				rst.fail("unterminated punycode")
   342  			}
   343  
   344  			var digit byte
   345  			d := encoding[pos]
   346  			pos++
   347  			switch {
   348  			case '0' <= d && d <= '9':
   349  				digit = d - '0' + 26
   350  			case 'A' <= d && d <= 'Z':
   351  				digit = d - 'A'
   352  			case 'a' <= d && d <= 'z':
   353  				digit = d - 'a'
   354  			default:
   355  				rst.fail("invalid punycode digit")
   356  			}
   357  
   358  			i += int(digit) * w
   359  			if i < 0 {
   360  				rst.fail("punycode number overflow")
   361  			}
   362  
   363  			var t int
   364  			if k <= bias {
   365  				t = tmin
   366  			} else if k > bias+tmax {
   367  				t = tmax
   368  			} else {
   369  				t = k - bias
   370  			}
   371  
   372  			if int(digit) < t {
   373  				break
   374  			}
   375  
   376  			if w >= math.MaxInt32/base {
   377  				rst.fail("punycode number overflow")
   378  			}
   379  			w *= base - t
   380  		}
   381  
   382  		delta := i - oldI
   383  		numPoints := len(output) + 1
   384  		firstTime := oldI == 0
   385  		if firstTime {
   386  			delta /= damp
   387  		} else {
   388  			delta /= 2
   389  		}
   390  		delta += delta / numPoints
   391  		k := 0
   392  		for delta > ((base-tmin)*tmax)/2 {
   393  			delta /= base - tmin
   394  			k += base
   395  		}
   396  		bias = k + ((base-tmin+1)*delta)/(delta+skew)
   397  
   398  		n += i / (len(output) + 1)
   399  		if n > utf8.MaxRune {
   400  			rst.fail("punycode rune overflow")
   401  		}
   402  		i %= len(output) + 1
   403  		output = append(output, 0)
   404  		copy(output[i+1:], output[i:])
   405  		output[i] = rune(n)
   406  		i++
   407  	}
   408  
   409  	return string(output)
   410  }
   411  
   412  // <generic-arg> = <lifetime>
   413  //               | <type>
   414  //               | "K" <const> // forward-compat for const generics
   415  // <lifetime> = "L" <base-62-number>
   416  func (rst *rustState) genericArg() {
   417  	if len(rst.str) < 1 {
   418  		rst.fail("expected generic-arg")
   419  	}
   420  	if rst.str[0] == 'L' {
   421  		rst.advance(1)
   422  		rst.writeLifetime(rst.base62Number())
   423  	} else if rst.str[0] == 'K' {
   424  		rst.advance(1)
   425  		rst.demangleConst()
   426  	} else {
   427  		rst.demangleType()
   428  	}
   429  }
   430  
   431  // <binder> = "G" <base-62-number>
   432  // This is optional.
   433  func (rst *rustState) binder() {
   434  	if len(rst.str) < 1 || rst.str[0] != 'G' {
   435  		return
   436  	}
   437  	rst.advance(1)
   438  
   439  	binderLifetimes := rst.base62Number() + 1
   440  
   441  	// Every bound lifetime should be referenced later.
   442  	if binderLifetimes >= int64(len(rst.str))-rst.lifetimes {
   443  		rst.fail("binder lifetimes overflow")
   444  	}
   445  
   446  	rst.writeString("for<")
   447  	for i := int64(0); i < binderLifetimes; i++ {
   448  		if i > 0 {
   449  			rst.writeString(", ")
   450  		}
   451  		rst.lifetimes++
   452  		rst.writeLifetime(1)
   453  	}
   454  	rst.writeString("> ")
   455  }
   456  
   457  // <type> = <basic-type>
   458  //        | <path>                      // named type
   459  //        | "A" <type> <const>          // [T; N]
   460  //        | "S" <type>                  // [T]
   461  //        | "T" {<type>} "E"            // (T1, T2, T3, ...)
   462  //        | "R" [<lifetime>] <type>     // &T
   463  //        | "Q" [<lifetime>] <type>     // &mut T
   464  //        | "P" <type>                  // *const T
   465  //        | "O" <type>                  // *mut T
   466  //        | "F" <fn-sig>                // fn(...) -> ...
   467  //        | "D" <dyn-bounds> <lifetime> // dyn Trait<Assoc = X> + Send + 'a
   468  //        | <backref>
   469  func (rst *rustState) demangleType() {
   470  	if len(rst.str) < 1 {
   471  		rst.fail("expected type")
   472  	}
   473  	c := rst.str[0]
   474  	if c >= 'a' && c <= 'z' {
   475  		rst.basicType()
   476  		return
   477  	}
   478  	switch c {
   479  	case 'C', 'M', 'X', 'Y', 'N', 'I':
   480  		rst.path(false)
   481  	case 'A', 'S':
   482  		rst.advance(1)
   483  		rst.writeByte('[')
   484  		rst.demangleType()
   485  		if c == 'A' {
   486  			rst.writeString("; ")
   487  			rst.demangleConst()
   488  		}
   489  		rst.writeByte(']')
   490  	case 'T':
   491  		rst.advance(1)
   492  		rst.writeByte('(')
   493  		c := 0
   494  		for len(rst.str) > 0 && rst.str[0] != 'E' {
   495  			if c > 0 {
   496  				rst.writeString(", ")
   497  			}
   498  			c++
   499  			rst.demangleType()
   500  		}
   501  		if c == 1 {
   502  			rst.writeByte(',')
   503  		}
   504  		rst.writeByte(')')
   505  		rst.checkChar('E')
   506  	case 'R', 'Q':
   507  		rst.advance(1)
   508  		rst.writeByte('&')
   509  		if len(rst.str) > 0 && rst.str[0] == 'L' {
   510  			rst.advance(1)
   511  			if lifetime := rst.base62Number(); lifetime > 0 {
   512  				rst.writeLifetime(lifetime)
   513  				rst.writeByte(' ')
   514  			}
   515  		}
   516  		if c == 'Q' {
   517  			rst.writeString("mut ")
   518  		}
   519  		rst.demangleType()
   520  	case 'P':
   521  		rst.advance(1)
   522  		rst.writeString("*const ")
   523  		rst.demangleType()
   524  	case 'O':
   525  		rst.advance(1)
   526  		rst.writeString("*mut ")
   527  		rst.demangleType()
   528  	case 'F':
   529  		rst.advance(1)
   530  		hold := rst.lifetimes
   531  		rst.fnSig()
   532  		rst.lifetimes = hold
   533  	case 'D':
   534  		rst.advance(1)
   535  		hold := rst.lifetimes
   536  		rst.dynBounds()
   537  		rst.lifetimes = hold
   538  		if len(rst.str) == 0 || rst.str[0] != 'L' {
   539  			rst.fail("expected L")
   540  		}
   541  		rst.advance(1)
   542  		if lifetime := rst.base62Number(); lifetime > 0 {
   543  			if rst.last != ' ' {
   544  				rst.writeByte(' ')
   545  			}
   546  			rst.writeString("+ ")
   547  			rst.writeLifetime(lifetime)
   548  		}
   549  	case 'B':
   550  		rst.backref(rst.demangleType)
   551  	default:
   552  		rst.fail("unrecognized character in type")
   553  	}
   554  }
   555  
   556  var rustBasicTypes = map[byte]string{
   557  	'a': "i8",
   558  	'b': "bool",
   559  	'c': "char",
   560  	'd': "f64",
   561  	'e': "str",
   562  	'f': "f32",
   563  	'h': "u8",
   564  	'i': "isize",
   565  	'j': "usize",
   566  	'l': "i32",
   567  	'm': "u32",
   568  	'n': "i128",
   569  	'o': "u128",
   570  	'p': "_",
   571  	's': "i16",
   572  	't': "u16",
   573  	'u': "()",
   574  	'v': "...",
   575  	'x': "i64",
   576  	'y': "u64",
   577  	'z': "!",
   578  }
   579  
   580  // <basic-type>
   581  func (rst *rustState) basicType() {
   582  	if len(rst.str) < 1 {
   583  		rst.fail("expected basic type")
   584  	}
   585  	str, ok := rustBasicTypes[rst.str[0]]
   586  	if !ok {
   587  		rst.fail("unrecognized basic type character")
   588  	}
   589  	rst.advance(1)
   590  	rst.writeString(str)
   591  }
   592  
   593  // <fn-sig> = [<binder>] ["U"] ["K" <abi>] {<type>} "E" <type>
   594  // <abi> = "C"
   595  //       | <undisambiguated-identifier>
   596  func (rst *rustState) fnSig() {
   597  	rst.binder()
   598  	if len(rst.str) > 0 && rst.str[0] == 'U' {
   599  		rst.advance(1)
   600  		rst.writeString("unsafe ")
   601  	}
   602  	if len(rst.str) > 0 && rst.str[0] == 'K' {
   603  		rst.advance(1)
   604  		if len(rst.str) > 0 && rst.str[0] == 'C' {
   605  			rst.advance(1)
   606  			rst.writeString(`extern "C" `)
   607  		} else {
   608  			rst.writeString(`extern "`)
   609  			id := rst.undisambiguatedIdentifier()
   610  			id = strings.ReplaceAll(id, "_", "-")
   611  			rst.writeString(id)
   612  			rst.writeString(`" `)
   613  		}
   614  	}
   615  	rst.writeString("fn(")
   616  	first := true
   617  	for len(rst.str) > 0 && rst.str[0] != 'E' {
   618  		if first {
   619  			first = false
   620  		} else {
   621  			rst.writeString(", ")
   622  		}
   623  		rst.demangleType()
   624  	}
   625  	rst.checkChar('E')
   626  	rst.writeByte(')')
   627  	if len(rst.str) > 0 && rst.str[0] == 'u' {
   628  		rst.advance(1)
   629  	} else {
   630  		rst.writeString(" -> ")
   631  		rst.demangleType()
   632  	}
   633  }
   634  
   635  // <dyn-bounds> = [<binder>] {<dyn-trait>} "E"
   636  func (rst *rustState) dynBounds() {
   637  	rst.writeString("dyn ")
   638  	rst.binder()
   639  	first := true
   640  	for len(rst.str) > 0 && rst.str[0] != 'E' {
   641  		if first {
   642  			first = false
   643  		} else {
   644  			rst.writeString(" + ")
   645  		}
   646  		rst.dynTrait()
   647  	}
   648  	rst.checkChar('E')
   649  }
   650  
   651  // <dyn-trait> = <path> {<dyn-trait-assoc-binding>}
   652  // <dyn-trait-assoc-binding> = "p" <undisambiguated-identifier> <type>
   653  func (rst *rustState) dynTrait() {
   654  	started := rst.pathStartGenerics()
   655  	for len(rst.str) > 0 && rst.str[0] == 'p' {
   656  		rst.advance(1)
   657  		if started {
   658  			rst.writeString(", ")
   659  		} else {
   660  			rst.writeByte('<')
   661  			started = true
   662  		}
   663  		rst.writeString(rst.undisambiguatedIdentifier())
   664  		rst.writeString(" = ")
   665  		rst.demangleType()
   666  	}
   667  	if started {
   668  		rst.writeByte('>')
   669  	}
   670  }
   671  
   672  // pathStartGenerics is like path but if it sees an I to start generic
   673  // arguments it won't close them. It reports whether it started generics.
   674  func (rst *rustState) pathStartGenerics() bool {
   675  	if len(rst.str) < 1 {
   676  		rst.fail("expected path")
   677  	}
   678  	switch rst.str[0] {
   679  	case 'I':
   680  		rst.advance(1)
   681  		rst.path(false)
   682  		rst.writeByte('<')
   683  		first := true
   684  		for len(rst.str) > 0 && rst.str[0] != 'E' {
   685  			if first {
   686  				first = false
   687  			} else {
   688  				rst.writeString(", ")
   689  			}
   690  			rst.genericArg()
   691  		}
   692  		rst.checkChar('E')
   693  		return true
   694  	case 'B':
   695  		var started bool
   696  		rst.backref(func() { started = rst.pathStartGenerics() })
   697  		return started
   698  	default:
   699  		rst.path(false)
   700  		return false
   701  	}
   702  }
   703  
   704  // writeLifetime writes out a lifetime binding.
   705  func (rst *rustState) writeLifetime(lifetime int64) {
   706  	rst.writeByte('\'')
   707  	if lifetime == 0 {
   708  		rst.writeByte('_')
   709  		return
   710  	}
   711  	depth := rst.lifetimes - lifetime
   712  	if depth < 0 {
   713  		rst.fail("invalid lifetime")
   714  	} else if depth < 26 {
   715  		rst.writeByte('a' + byte(depth))
   716  	} else {
   717  		rst.writeByte('z')
   718  		if !rst.skip {
   719  			fmt.Fprintf(&rst.buf, "%d", depth-26+1)
   720  			rst.last = '0'
   721  		}
   722  	}
   723  }
   724  
   725  // <const> = <type> <const-data>
   726  //         | "p" // placeholder, shown as _
   727  //         | <backref>
   728  // <const-data> = ["n"] {<hex-digit>} "_"
   729  func (rst *rustState) demangleConst() {
   730  	if len(rst.str) < 1 {
   731  		rst.fail("expected constant")
   732  	}
   733  
   734  	if rst.str[0] == 'B' {
   735  		rst.backref(rst.demangleConst)
   736  		return
   737  	}
   738  
   739  	if rst.str[0] == 'p' {
   740  		rst.advance(1)
   741  		rst.writeByte('_')
   742  		return
   743  	}
   744  
   745  	typ := rst.str[0]
   746  
   747  	const (
   748  		invalid = iota
   749  		signedInt
   750  		unsignedInt
   751  		boolean
   752  		character
   753  	)
   754  
   755  	var kind int
   756  	switch typ {
   757  	case 'a', 's', 'l', 'x', 'n', 'i':
   758  		kind = signedInt
   759  	case 'h', 't', 'm', 'y', 'o', 'j':
   760  		kind = unsignedInt
   761  	case 'b':
   762  		kind = boolean
   763  	case 'c':
   764  		kind = character
   765  	default:
   766  		rst.fail("unrecognized constant type")
   767  	}
   768  
   769  	rst.advance(1)
   770  
   771  	if kind == signedInt && len(rst.str) > 0 && rst.str[0] == 'n' {
   772  		rst.advance(1)
   773  		rst.writeByte('-')
   774  	}
   775  
   776  	start := rst.str
   777  	digits := 0
   778  	val := uint64(0)
   779  digitLoop:
   780  	for len(rst.str) > 0 {
   781  		c := rst.str[0]
   782  		var digit uint64
   783  		switch {
   784  		case c >= '0' && c <= '9':
   785  			digit = uint64(c - '0')
   786  		case c >= 'a' && c <= 'f':
   787  			digit = uint64(c - 'a' + 10)
   788  		case c == '_':
   789  			rst.advance(1)
   790  			break digitLoop
   791  		default:
   792  			rst.fail("expected hex digit or _")
   793  		}
   794  		rst.advance(1)
   795  		if val == 0 && digit == 0 && (len(rst.str) == 0 || rst.str[0] != '_') {
   796  			rst.fail("invalid leading 0 in constant")
   797  		}
   798  		val *= 16
   799  		val += digit
   800  		digits++
   801  	}
   802  
   803  	if digits == 0 {
   804  		rst.fail("expected constant")
   805  	}
   806  
   807  	switch kind {
   808  	case signedInt, unsignedInt:
   809  		if digits > 16 {
   810  			// Value too big, just write out the string.
   811  			rst.writeString("0x")
   812  			rst.writeString(start[:digits])
   813  		} else {
   814  			if !rst.skip {
   815  				fmt.Fprintf(&rst.buf, "%d", val)
   816  				rst.last = '0'
   817  			}
   818  		}
   819  	case boolean:
   820  		if digits > 1 {
   821  			rst.fail("boolean value too large")
   822  		} else if val == 0 {
   823  			rst.writeString("false")
   824  		} else if val == 1 {
   825  			rst.writeString("true")
   826  		} else {
   827  			rst.fail("invalid boolean value")
   828  		}
   829  	case character:
   830  		if digits > 6 {
   831  			rst.fail("character value too large")
   832  		}
   833  		rst.writeByte('\'')
   834  		if val == '\t' {
   835  			rst.writeString(`\t`)
   836  		} else if val == '\r' {
   837  			rst.writeString(`\r`)
   838  		} else if val == '\n' {
   839  			rst.writeString(`\n`)
   840  		} else if val == '\\' {
   841  			rst.writeString(`\\`)
   842  		} else if val == '\'' {
   843  			rst.writeString(`\'`)
   844  		} else if val >= ' ' && val <= '~' {
   845  			// printable ASCII character
   846  			rst.writeByte(byte(val))
   847  		} else {
   848  			if !rst.skip {
   849  				fmt.Fprintf(&rst.buf, `\u{%x}`, val)
   850  				rst.last = '}'
   851  			}
   852  		}
   853  		rst.writeByte('\'')
   854  	default:
   855  		panic("internal error")
   856  	}
   857  }
   858  
   859  // <base-62-number> = {<0-9a-zA-Z>} "_"
   860  func (rst *rustState) base62Number() int64 {
   861  	if len(rst.str) > 0 && rst.str[0] == '_' {
   862  		rst.advance(1)
   863  		return 0
   864  	}
   865  	val := int64(0)
   866  	for len(rst.str) > 0 {
   867  		c := rst.str[0]
   868  		rst.advance(1)
   869  		if c == '_' {
   870  			return val + 1
   871  		}
   872  		val *= 62
   873  		if c >= '0' && c <= '9' {
   874  			val += int64(c - '0')
   875  		} else if c >= 'a' && c <= 'z' {
   876  			val += int64(c - 'a' + 10)
   877  		} else if c >= 'A' && c <= 'Z' {
   878  			val += int64(c - 'A' + 36)
   879  		} else {
   880  			rst.fail("invalid digit in base 62 number")
   881  		}
   882  	}
   883  	rst.fail("expected _ after base 62 number")
   884  	return 0
   885  }
   886  
   887  // <backref> = "B" <base-62-number>
   888  func (rst *rustState) backref(demangle func()) {
   889  	backoff := rst.off
   890  
   891  	rst.checkChar('B')
   892  	idx64 := rst.base62Number()
   893  
   894  	if rst.skip {
   895  		return
   896  	}
   897  
   898  	idx := int(idx64)
   899  	if int64(idx) != idx64 {
   900  		rst.fail("backref index overflow")
   901  	}
   902  	if idx < 0 || idx >= backoff {
   903  		rst.fail("invalid backref index")
   904  	}
   905  
   906  	holdStr := rst.str
   907  	holdOff := rst.off
   908  	rst.str = rst.orig[idx:backoff]
   909  	rst.off = idx
   910  	defer func() {
   911  		rst.str = holdStr
   912  		rst.off = holdOff
   913  	}()
   914  
   915  	demangle()
   916  }
   917  
   918  func (rst *rustState) decimalNumber() int {
   919  	if len(rst.str) == 0 {
   920  		rst.fail("expected number")
   921  	}
   922  
   923  	val := 0
   924  	for len(rst.str) > 0 && isDigit(rst.str[0]) {
   925  		add := int(rst.str[0] - '0')
   926  		if val >= math.MaxInt32/10-add {
   927  			rst.fail("decimal number overflow")
   928  		}
   929  		val *= 10
   930  		val += add
   931  		rst.advance(1)
   932  	}
   933  	return val
   934  }
   935  
   936  // oldRustToString demangles a Rust symbol using the old demangling.
   937  // The second result reports whether this is a valid Rust mangled name.
   938  func oldRustToString(name string, options []Option) (string, bool) {
   939  	// We know that the string starts with _ZN.
   940  	name = name[3:]
   941  
   942  	hexDigit := func(c byte) (byte, bool) {
   943  		switch {
   944  		case c >= '0' && c <= '9':
   945  			return c - '0', true
   946  		case c >= 'a' && c <= 'f':
   947  			return c - 'a' + 10, true
   948  		default:
   949  			return 0, false
   950  		}
   951  	}
   952  
   953  	// We know that the strings end with "17h" followed by 16 characters
   954  	// followed by "E". We check that the 16 characters are all hex digits.
   955  	// Also the hex digits must contain at least 5 distinct digits.
   956  	seen := uint16(0)
   957  	for i := len(name) - 17; i < len(name) - 1; i++ {
   958  		digit, ok := hexDigit(name[i])
   959  		if !ok {
   960  			return "", false
   961  		}
   962  		seen |= 1 << digit
   963  	}
   964  	if bits.OnesCount16(seen) < 5 {
   965  		return "", false
   966  	}
   967  	name = name[:len(name)-20]
   968  
   969  	// The name is a sequence of length-preceded identifiers.
   970  	var sb strings.Builder
   971  	for len(name) > 0 {
   972  		if !isDigit(name[0]) {
   973  			return "", false
   974  		}
   975  
   976  		val := 0
   977  		for len(name) > 0 && isDigit(name[0]) {
   978  			add := int(name[0] - '0')
   979  			if val >= math.MaxInt32/10-add {
   980  				return "", false
   981  			}
   982  			val *= 10
   983  			val += add
   984  			name = name[1:]
   985  		}
   986  
   987  		// An optional trailing underscore can separate the
   988  		// length from the identifier.
   989  		if len(name) > 0 && name[0] == '_' {
   990  			name = name[1:]
   991  			val--
   992  		}
   993  
   994  		if len(name) < val {
   995  			return "", false
   996  		}
   997  
   998  		id := name[:val]
   999  		name = name[val:]
  1000  
  1001  		if sb.Len() > 0 {
  1002  			sb.WriteString("::")
  1003  		}
  1004  
  1005  		// Ignore leading underscores preceding escape sequences.
  1006  		if strings.HasPrefix(id, "_$") {
  1007  			id = id[1:]
  1008  		}
  1009  
  1010  		// The identifier can have escape sequences.
  1011  	escape:
  1012  		for len(id) > 0 {
  1013  			switch c := id[0]; c {
  1014  			case '$':
  1015  				codes := map[string]byte {
  1016  					"SP": '@',
  1017  					"BP": '*',
  1018  					"RF": '&',
  1019  					"LT": '<',
  1020  					"GT": '>',
  1021  					"LP": '(',
  1022  					"RP": ')',
  1023  				}
  1024  
  1025  				valid := true
  1026  				if len(id) > 2 && id[1] == 'C' && id[2] == '$' {
  1027  					sb.WriteByte(',')
  1028  					id = id[3:]
  1029  				} else if len(id) > 4 && id[1] == 'u' && id[4] == '$' {
  1030  					dig1, ok1 := hexDigit(id[2])
  1031  					dig2, ok2 := hexDigit(id[3])
  1032  					val := (dig1 << 4) | dig2
  1033  					if !ok1 || !ok2 || dig1 > 7 || val < ' ' {
  1034  						valid = false
  1035  					} else {
  1036  						sb.WriteByte(val)
  1037  						id = id[5:]
  1038  					}
  1039  				} else if len(id) > 3 && id[3] == '$' {
  1040  					if code, ok := codes[id[1:3]]; !ok {
  1041  						valid = false
  1042  					} else {
  1043  						sb.WriteByte(code)
  1044  						id = id[4:]
  1045  					}
  1046  				} else {
  1047  					valid = false
  1048  				}
  1049  				if !valid {
  1050  					sb.WriteString(id)
  1051  					break escape
  1052  				}
  1053  			case '.':
  1054  				if strings.HasPrefix(id, "..") {
  1055  					sb.WriteString("::")
  1056  					id = id[2:]
  1057  				} else {
  1058  					sb.WriteByte(c)
  1059  					id = id[1:]
  1060  				}
  1061  			default:
  1062  				sb.WriteByte(c)
  1063  				id = id[1:]
  1064  			}
  1065  		}
  1066  	}
  1067  
  1068  	return sb.String(), true
  1069  }
  1070  

View as plain text