trpc.group/trpc-go/trpc-go@v1.0.3/codec/message_impl.go (about)

     1  //
     2  //
     3  // Tencent is pleased to support the open source community by making tRPC available.
     4  //
     5  // Copyright (C) 2023 THL A29 Limited, a Tencent company.
     6  // All rights reserved.
     7  //
     8  // If you have downloaded a copy of the tRPC source code from Tencent,
     9  // please note that tRPC source code is licensed under the  Apache 2.0 License,
    10  // A copy of the Apache 2.0 License is included in this file.
    11  //
    12  //
    13  
    14  package codec
    15  
    16  import (
    17  	"context"
    18  	"net"
    19  	"strings"
    20  	"time"
    21  
    22  	"trpc.group/trpc-go/trpc-go/errs"
    23  )
    24  
    25  // msg is the context of rpc.
    26  type msg struct {
    27  	context             context.Context
    28  	frameHead           interface{}
    29  	requestTimeout      time.Duration
    30  	serializationType   int
    31  	compressType        int
    32  	streamID            uint32
    33  	dyeing              bool
    34  	dyeingKey           string
    35  	serverRPCName       string
    36  	clientRPCName       string
    37  	serverMetaData      MetaData
    38  	clientMetaData      MetaData
    39  	callerServiceName   string
    40  	calleeServiceName   string
    41  	calleeContainerName string
    42  	serverRspErr        error
    43  	clientRspErr        error
    44  	serverReqHead       interface{}
    45  	serverRspHead       interface{}
    46  	clientReqHead       interface{}
    47  	clientRspHead       interface{}
    48  	localAddr           net.Addr
    49  	remoteAddr          net.Addr
    50  	logger              interface{}
    51  	callerApp           string
    52  	callerServer        string
    53  	callerService       string
    54  	callerMethod        string
    55  	calleeApp           string
    56  	calleeServer        string
    57  	calleeService       string
    58  	calleeMethod        string
    59  	namespace           string
    60  	setName             string
    61  	envName             string
    62  	envTransfer         string
    63  	requestID           uint32
    64  	calleeSetName       string
    65  	streamFrame         interface{}
    66  	commonMeta          CommonMeta
    67  	callType            RequestType
    68  }
    69  
    70  // resetDefault reset all fields of msg to default value.
    71  func (m *msg) resetDefault() {
    72  	m.context = nil
    73  	m.frameHead = nil
    74  	m.requestTimeout = 0
    75  	m.serializationType = 0
    76  	m.compressType = 0
    77  	m.dyeing = false
    78  	m.dyeingKey = ""
    79  	m.serverRPCName = ""
    80  	m.clientRPCName = ""
    81  	m.serverMetaData = nil
    82  	m.clientMetaData = nil
    83  	m.callerServiceName = ""
    84  	m.calleeServiceName = ""
    85  	m.calleeContainerName = ""
    86  	m.serverRspErr = nil
    87  	m.clientRspErr = nil
    88  	m.serverReqHead = nil
    89  	m.serverRspHead = nil
    90  	m.clientReqHead = nil
    91  	m.clientRspHead = nil
    92  	m.localAddr = nil
    93  	m.remoteAddr = nil
    94  	m.logger = nil
    95  	m.callerApp = ""
    96  	m.callerServer = ""
    97  	m.callerService = ""
    98  	m.callerMethod = ""
    99  	m.calleeApp = ""
   100  	m.calleeServer = ""
   101  	m.calleeService = ""
   102  	m.calleeMethod = ""
   103  	m.namespace = ""
   104  	m.setName = ""
   105  	m.envName = ""
   106  	m.envTransfer = ""
   107  	m.requestID = 0
   108  	m.streamFrame = nil
   109  	m.streamID = 0
   110  	m.calleeSetName = ""
   111  	m.commonMeta = nil
   112  	m.callType = 0
   113  }
   114  
   115  // Context restores old context when create new msg.
   116  func (m *msg) Context() context.Context {
   117  	return m.context
   118  }
   119  
   120  // WithNamespace set server's namespace.
   121  func (m *msg) WithNamespace(namespace string) {
   122  	m.namespace = namespace
   123  }
   124  
   125  // Namespace returns namespace.
   126  func (m *msg) Namespace() string {
   127  	return m.namespace
   128  }
   129  
   130  // WithEnvName sets environment.
   131  func (m *msg) WithEnvName(envName string) {
   132  	m.envName = envName
   133  }
   134  
   135  // WithSetName sets set name.
   136  func (m *msg) WithSetName(setName string) {
   137  	m.setName = setName
   138  }
   139  
   140  // SetName returns set name.
   141  func (m *msg) SetName() string {
   142  	return m.setName
   143  }
   144  
   145  // WithCalleeSetName sets the callee set name.
   146  func (m *msg) WithCalleeSetName(s string) {
   147  	m.calleeSetName = s
   148  }
   149  
   150  // CalleeSetName returns the callee set name.
   151  func (m *msg) CalleeSetName() string {
   152  	return m.calleeSetName
   153  }
   154  
   155  // EnvName returns environment.
   156  func (m *msg) EnvName() string {
   157  	return m.envName
   158  }
   159  
   160  // WithEnvTransfer sets environment transfer value.
   161  func (m *msg) WithEnvTransfer(envTransfer string) {
   162  	m.envTransfer = envTransfer
   163  }
   164  
   165  // EnvTransfer returns environment transfer value.
   166  func (m *msg) EnvTransfer() string {
   167  	return m.envTransfer
   168  }
   169  
   170  // WithRemoteAddr sets remote address.
   171  func (m *msg) WithRemoteAddr(addr net.Addr) {
   172  	m.remoteAddr = addr
   173  }
   174  
   175  // WithLocalAddr set local address.
   176  func (m *msg) WithLocalAddr(addr net.Addr) {
   177  	m.localAddr = addr
   178  }
   179  
   180  // RemoteAddr returns remote address.
   181  func (m *msg) RemoteAddr() net.Addr {
   182  	return m.remoteAddr
   183  }
   184  
   185  // LocalAddr returns local address.
   186  func (m *msg) LocalAddr() net.Addr {
   187  	return m.localAddr
   188  }
   189  
   190  // RequestTimeout returns request timeout set by
   191  // upstream business protocol.
   192  func (m *msg) RequestTimeout() time.Duration {
   193  	return m.requestTimeout
   194  }
   195  
   196  // WithRequestTimeout sets request timeout.
   197  func (m *msg) WithRequestTimeout(t time.Duration) {
   198  	m.requestTimeout = t
   199  }
   200  
   201  // FrameHead returns frame head.
   202  func (m *msg) FrameHead() interface{} {
   203  	return m.frameHead
   204  }
   205  
   206  // WithFrameHead sets frame head.
   207  func (m *msg) WithFrameHead(f interface{}) {
   208  	m.frameHead = f
   209  }
   210  
   211  // SerializationType returns the value of body serialization, which is
   212  // defined in serialization.go.
   213  func (m *msg) SerializationType() int {
   214  	return m.serializationType
   215  }
   216  
   217  // WithSerializationType sets body serialization type of body.
   218  func (m *msg) WithSerializationType(t int) {
   219  	m.serializationType = t
   220  }
   221  
   222  // CompressType returns compress type value, which is defined in compress.go.
   223  func (m *msg) CompressType() int {
   224  	return m.compressType
   225  }
   226  
   227  // WithCompressType sets compress type.
   228  func (m *msg) WithCompressType(t int) {
   229  	m.compressType = t
   230  }
   231  
   232  // ServerRPCName returns server rpc name.
   233  func (m *msg) ServerRPCName() string {
   234  	return m.serverRPCName
   235  }
   236  
   237  // WithServerRPCName sets server rpc name.
   238  func (m *msg) WithServerRPCName(s string) {
   239  	if m.serverRPCName == s {
   240  		return
   241  	}
   242  	m.serverRPCName = s
   243  	m.updateMethodNameUsingRPCName(s)
   244  }
   245  
   246  // ClientRPCName returns client rpc name.
   247  func (m *msg) ClientRPCName() string {
   248  	return m.clientRPCName
   249  }
   250  
   251  // WithClientRPCName sets client rpc name, which will be called
   252  // by client stub.
   253  func (m *msg) WithClientRPCName(s string) {
   254  	if m.clientRPCName == s {
   255  		return
   256  	}
   257  	m.clientRPCName = s
   258  	m.updateMethodNameUsingRPCName(s)
   259  }
   260  
   261  func (m *msg) updateMethodNameUsingRPCName(s string) {
   262  	if rpcNameIsTRPCForm(s) {
   263  		m.WithCalleeMethod(methodFromRPCName(s))
   264  		return
   265  	}
   266  	if m.CalleeMethod() == "" {
   267  		m.WithCalleeMethod(s)
   268  	}
   269  }
   270  
   271  // ServerMetaData returns server meta data, which is passed to server.
   272  func (m *msg) ServerMetaData() MetaData {
   273  	return m.serverMetaData
   274  }
   275  
   276  // WithServerMetaData sets server meta data.
   277  func (m *msg) WithServerMetaData(d MetaData) {
   278  	if d == nil {
   279  		d = MetaData{}
   280  	}
   281  	m.serverMetaData = d
   282  }
   283  
   284  // ClientMetaData returns client meta data, which will pass to downstream.
   285  func (m *msg) ClientMetaData() MetaData {
   286  	return m.clientMetaData
   287  }
   288  
   289  // WithClientMetaData set client meta data.
   290  func (m *msg) WithClientMetaData(d MetaData) {
   291  	if d == nil {
   292  		d = MetaData{}
   293  	}
   294  	m.clientMetaData = d
   295  }
   296  
   297  // CalleeServiceName returns callee service name.
   298  func (m *msg) CalleeServiceName() string {
   299  	return m.calleeServiceName
   300  }
   301  
   302  // WithCalleeServiceName sets callee service name.
   303  func (m *msg) WithCalleeServiceName(s string) {
   304  	if m.calleeServiceName == s {
   305  		return
   306  	}
   307  	m.calleeServiceName = s
   308  	if s == "*" {
   309  		return
   310  	}
   311  	app, server, service := getAppServerService(s)
   312  	m.WithCalleeApp(app)
   313  	m.WithCalleeServer(server)
   314  	m.WithCalleeService(service)
   315  }
   316  
   317  // CalleeContainerName returns callee container name.
   318  func (m *msg) CalleeContainerName() string {
   319  	return m.calleeContainerName
   320  }
   321  
   322  // WithCalleeContainerName sets callee container name.
   323  func (m *msg) WithCalleeContainerName(s string) {
   324  	m.calleeContainerName = s
   325  }
   326  
   327  // WithStreamFrame sets stream frame.
   328  func (m *msg) WithStreamFrame(i interface{}) {
   329  	m.streamFrame = i
   330  }
   331  
   332  // StreamFrame returns stream frame.
   333  func (m *msg) StreamFrame() interface{} {
   334  	return m.streamFrame
   335  }
   336  
   337  // CallerServiceName returns caller service name.
   338  func (m *msg) CallerServiceName() string {
   339  	return m.callerServiceName
   340  }
   341  
   342  // WithCallerServiceName sets caller service name.
   343  func (m *msg) WithCallerServiceName(s string) {
   344  	if m.callerServiceName == s {
   345  		return
   346  	}
   347  	m.callerServiceName = s
   348  	if s == "*" {
   349  		return
   350  	}
   351  	app, server, service := getAppServerService(s)
   352  	m.WithCallerApp(app)
   353  	m.WithCallerServer(server)
   354  	m.WithCallerService(service)
   355  }
   356  
   357  // ServerRspErr returns server response error, which is created
   358  // by handler.
   359  func (m *msg) ServerRspErr() *errs.Error {
   360  	if m.serverRspErr == nil {
   361  		return nil
   362  	}
   363  	e, ok := m.serverRspErr.(*errs.Error)
   364  	if !ok {
   365  		return &errs.Error{
   366  			Type: errs.ErrorTypeBusiness,
   367  			Code: errs.RetUnknown,
   368  			Msg:  m.serverRspErr.Error(),
   369  		}
   370  	}
   371  	return e
   372  }
   373  
   374  // WithServerRspErr sets server response error.
   375  func (m *msg) WithServerRspErr(e error) {
   376  	m.serverRspErr = e
   377  }
   378  
   379  // WithStreamID sets stream id.
   380  func (m *msg) WithStreamID(streamID uint32) {
   381  	m.streamID = streamID
   382  }
   383  
   384  // StreamID returns stream id.
   385  func (m *msg) StreamID() uint32 {
   386  	return m.streamID
   387  }
   388  
   389  // ClientRspErr returns client response error, which created when client call downstream.
   390  func (m *msg) ClientRspErr() error {
   391  	return m.clientRspErr
   392  }
   393  
   394  // WithClientRspErr sets client response err, this method will called
   395  // when client parse response package.
   396  func (m *msg) WithClientRspErr(e error) {
   397  	m.clientRspErr = e
   398  }
   399  
   400  // ServerReqHead returns the package head of request
   401  func (m *msg) ServerReqHead() interface{} {
   402  	return m.serverReqHead
   403  }
   404  
   405  // WithServerReqHead sets the package head of request
   406  func (m *msg) WithServerReqHead(h interface{}) {
   407  	m.serverReqHead = h
   408  }
   409  
   410  // ServerRspHead returns the package head of response
   411  func (m *msg) ServerRspHead() interface{} {
   412  	return m.serverRspHead
   413  }
   414  
   415  // WithServerRspHead sets the package head returns to upstream
   416  func (m *msg) WithServerRspHead(h interface{}) {
   417  	m.serverRspHead = h
   418  }
   419  
   420  // ClientReqHead returns the request package head of client,
   421  // this is set only when cross protocol call.
   422  func (m *msg) ClientReqHead() interface{} {
   423  	return m.clientReqHead
   424  }
   425  
   426  // WithClientReqHead sets the request package head of client.
   427  func (m *msg) WithClientReqHead(h interface{}) {
   428  	m.clientReqHead = h
   429  }
   430  
   431  // ClientRspHead returns the request package head of client.
   432  func (m *msg) ClientRspHead() interface{} {
   433  	return m.clientRspHead
   434  }
   435  
   436  // WithClientRspHead sets the response package head of client.
   437  func (m *msg) WithClientRspHead(h interface{}) {
   438  	m.clientRspHead = h
   439  }
   440  
   441  // Dyeing return the dyeing mark.
   442  func (m *msg) Dyeing() bool {
   443  	return m.dyeing
   444  }
   445  
   446  // WithDyeing sets the dyeing mark.
   447  func (m *msg) WithDyeing(dyeing bool) {
   448  	m.dyeing = dyeing
   449  }
   450  
   451  // DyeingKey returns the dyeing key.
   452  func (m *msg) DyeingKey() string {
   453  	return m.dyeingKey
   454  }
   455  
   456  // WithDyeingKey sets the dyeing key.
   457  func (m *msg) WithDyeingKey(key string) {
   458  	m.dyeingKey = key
   459  }
   460  
   461  // CallerApp returns caller app.
   462  func (m *msg) CallerApp() string {
   463  	return m.callerApp
   464  }
   465  
   466  // WithCallerApp sets caller app.
   467  func (m *msg) WithCallerApp(app string) {
   468  	m.callerApp = app
   469  }
   470  
   471  // CallerServer returns caller server.
   472  func (m *msg) CallerServer() string {
   473  	return m.callerServer
   474  }
   475  
   476  // WithCallerServer sets caller server.
   477  func (m *msg) WithCallerServer(s string) {
   478  	m.callerServer = s
   479  }
   480  
   481  // CallerService returns caller service.
   482  func (m *msg) CallerService() string {
   483  	return m.callerService
   484  }
   485  
   486  // WithCallerService sets caller service.
   487  func (m *msg) WithCallerService(s string) {
   488  	m.callerService = s
   489  }
   490  
   491  // WithCallerMethod sets caller method.
   492  func (m *msg) WithCallerMethod(s string) {
   493  	m.callerMethod = s
   494  }
   495  
   496  // CallerMethod returns caller method.
   497  func (m *msg) CallerMethod() string {
   498  	return m.callerMethod
   499  }
   500  
   501  // CalleeApp returns caller app.
   502  func (m *msg) CalleeApp() string {
   503  	return m.calleeApp
   504  }
   505  
   506  // WithCalleeApp sets callee app.
   507  func (m *msg) WithCalleeApp(app string) {
   508  	m.calleeApp = app
   509  }
   510  
   511  // CalleeServer returns callee server.
   512  func (m *msg) CalleeServer() string {
   513  	return m.calleeServer
   514  }
   515  
   516  // WithCalleeServer sets callee server.
   517  func (m *msg) WithCalleeServer(s string) {
   518  	m.calleeServer = s
   519  }
   520  
   521  // CalleeService returns callee service.
   522  func (m *msg) CalleeService() string {
   523  	return m.calleeService
   524  }
   525  
   526  // WithCalleeService sets callee service.
   527  func (m *msg) WithCalleeService(s string) {
   528  	m.calleeService = s
   529  }
   530  
   531  // WithCalleeMethod sets callee method.
   532  func (m *msg) WithCalleeMethod(s string) {
   533  	m.calleeMethod = s
   534  }
   535  
   536  // CalleeMethod returns callee method.
   537  func (m *msg) CalleeMethod() string {
   538  	return m.calleeMethod
   539  }
   540  
   541  // WithLogger sets logger into context message. Generally, the logger is
   542  // created from WithFields() method.
   543  func (m *msg) WithLogger(l interface{}) {
   544  	m.logger = l
   545  }
   546  
   547  // Logger returns logger from context message.
   548  func (m *msg) Logger() interface{} {
   549  	return m.logger
   550  }
   551  
   552  // WithRequestID sets request id.
   553  func (m *msg) WithRequestID(id uint32) {
   554  	m.requestID = id
   555  }
   556  
   557  // RequestID returns request id.
   558  func (m *msg) RequestID() uint32 {
   559  	return m.requestID
   560  }
   561  
   562  // WithCommonMeta sets common meta data.
   563  func (m *msg) WithCommonMeta(c CommonMeta) {
   564  	m.commonMeta = c
   565  }
   566  
   567  // CommonMeta returns common meta data.
   568  func (m *msg) CommonMeta() CommonMeta {
   569  	return m.commonMeta
   570  }
   571  
   572  // WithCallType sets type of call.
   573  func (m *msg) WithCallType(t RequestType) {
   574  	m.callType = t
   575  }
   576  
   577  // CallType returns type of call.
   578  func (m *msg) CallType() RequestType {
   579  	return m.callType
   580  }
   581  
   582  // WithNewMessage create a new empty message, and put it into ctx,
   583  func WithNewMessage(ctx context.Context) (context.Context, Msg) {
   584  
   585  	m := msgPool.Get().(*msg)
   586  	ctx = context.WithValue(ctx, ContextKeyMessage, m)
   587  	m.context = ctx
   588  	return ctx, m
   589  }
   590  
   591  // PutBackMessage return struct Message to sync pool,
   592  // and reset all the members of Message to default
   593  func PutBackMessage(sourceMsg Msg) {
   594  	m, ok := sourceMsg.(*msg)
   595  	if !ok {
   596  		return
   597  	}
   598  	m.resetDefault()
   599  	msgPool.Put(m)
   600  }
   601  
   602  // WithCloneContextAndMessage creates a new context, then copy the message of current context
   603  // into new context, this method will return the new context and message for stream mod.
   604  func WithCloneContextAndMessage(ctx context.Context) (context.Context, Msg) {
   605  	newMsg := msgPool.Get().(*msg)
   606  	newCtx := context.Background()
   607  	val := ctx.Value(ContextKeyMessage)
   608  	m, ok := val.(*msg)
   609  	if !ok {
   610  		newCtx = context.WithValue(newCtx, ContextKeyMessage, newMsg)
   611  		newMsg.context = newCtx
   612  		return newCtx, newMsg
   613  	}
   614  	newCtx = context.WithValue(newCtx, ContextKeyMessage, newMsg)
   615  	newMsg.context = newCtx
   616  	copyCommonMessage(m, newMsg)
   617  	copyServerToServerMessage(m, newMsg)
   618  	return newCtx, newMsg
   619  }
   620  
   621  // copyCommonMessage copy common data of message.
   622  func copyCommonMessage(m *msg, newMsg *msg) {
   623  	// Do not copy compress type here, as it will cause subsequence RPC calls to inherit the upstream
   624  	// compress type which is not the expected behavior. Compress type should not be propagated along
   625  	// the entire RPC invocation chain.
   626  	newMsg.frameHead = m.frameHead
   627  	newMsg.requestTimeout = m.requestTimeout
   628  	newMsg.serializationType = m.serializationType
   629  	newMsg.serverRPCName = m.serverRPCName
   630  	newMsg.clientRPCName = m.clientRPCName
   631  	newMsg.serverReqHead = m.serverReqHead
   632  	newMsg.serverRspHead = m.serverRspHead
   633  	newMsg.dyeing = m.dyeing
   634  	newMsg.dyeingKey = m.dyeingKey
   635  	newMsg.serverMetaData = m.serverMetaData.Clone()
   636  	newMsg.logger = m.logger
   637  	newMsg.namespace = m.namespace
   638  	newMsg.envName = m.envName
   639  	newMsg.setName = m.setName
   640  	newMsg.envTransfer = m.envTransfer
   641  	newMsg.commonMeta = m.commonMeta.Clone()
   642  }
   643  
   644  // copyClientMessage copy the message transferred from server to client.
   645  func copyServerToClientMessage(m *msg, newMsg *msg) {
   646  	newMsg.clientMetaData = m.serverMetaData.Clone()
   647  	// clone this message for downstream client, so caller is equal to callee.
   648  	newMsg.callerServiceName = m.calleeServiceName
   649  	newMsg.callerApp = m.calleeApp
   650  	newMsg.callerServer = m.calleeServer
   651  	newMsg.callerService = m.calleeService
   652  	newMsg.callerMethod = m.calleeMethod
   653  }
   654  
   655  func copyServerToServerMessage(m *msg, newMsg *msg) {
   656  	newMsg.callerServiceName = m.callerServiceName
   657  	newMsg.callerApp = m.callerApp
   658  	newMsg.callerServer = m.callerServer
   659  	newMsg.callerService = m.callerService
   660  	newMsg.callerMethod = m.callerMethod
   661  
   662  	newMsg.calleeServiceName = m.calleeServiceName
   663  	newMsg.calleeService = m.calleeService
   664  	newMsg.calleeApp = m.calleeApp
   665  	newMsg.calleeServer = m.calleeServer
   666  	newMsg.calleeMethod = m.calleeMethod
   667  }
   668  
   669  // WithCloneMessage copy a new message and put into context, each rpc call should
   670  // create a new message, this method will be called by client stub.
   671  func WithCloneMessage(ctx context.Context) (context.Context, Msg) {
   672  	newMsg := msgPool.Get().(*msg)
   673  	val := ctx.Value(ContextKeyMessage)
   674  	m, ok := val.(*msg)
   675  	if !ok {
   676  		ctx = context.WithValue(ctx, ContextKeyMessage, newMsg)
   677  		newMsg.context = ctx
   678  		return ctx, newMsg
   679  	}
   680  	ctx = context.WithValue(ctx, ContextKeyMessage, newMsg)
   681  	newMsg.context = ctx
   682  	copyCommonMessage(m, newMsg)
   683  	copyServerToClientMessage(m, newMsg)
   684  	return ctx, newMsg
   685  }
   686  
   687  // Message returns the message of context.
   688  func Message(ctx context.Context) Msg {
   689  	val := ctx.Value(ContextKeyMessage)
   690  	m, ok := val.(*msg)
   691  	if !ok {
   692  		return &msg{context: ctx}
   693  	}
   694  	return m
   695  }
   696  
   697  // EnsureMessage returns context and message, if there is a message in context,
   698  // returns the original one, if not, returns a new one.
   699  func EnsureMessage(ctx context.Context) (context.Context, Msg) {
   700  	val := ctx.Value(ContextKeyMessage)
   701  	if m, ok := val.(*msg); ok {
   702  		return ctx, m
   703  	}
   704  	return WithNewMessage(ctx)
   705  }
   706  
   707  // getAppServerService returns app, server and service parsed from service name.
   708  // service name example: trpc.app.server.service
   709  func getAppServerService(s string) (app, server, service string) {
   710  	if strings.Count(s, ".") >= ServiceSectionLength-1 {
   711  		i := strings.Index(s, ".") + 1
   712  		j := strings.Index(s[i:], ".") + i + 1
   713  		k := strings.Index(s[j:], ".") + j + 1
   714  		app = s[i : j-1]
   715  		server = s[j : k-1]
   716  		service = s[k:]
   717  		return
   718  	}
   719  	// app
   720  	i := strings.Index(s, ".")
   721  	if i == -1 {
   722  		app = s
   723  		return
   724  	}
   725  	app = s[:i]
   726  	// server
   727  	i++
   728  	j := strings.Index(s[i:], ".")
   729  	if j == -1 {
   730  		server = s[i:]
   731  		return
   732  	}
   733  	j += i + 1
   734  	server = s[i : j-1]
   735  	// service
   736  	service = s[j:]
   737  	return
   738  }
   739  
   740  // methodFromRPCName returns the method parsed from rpc string.
   741  func methodFromRPCName(s string) string {
   742  	return s[strings.LastIndex(s, "/")+1:]
   743  }
   744  
   745  // rpcNameIsTRPCForm checks whether the given string is of trpc form.
   746  // It is equivalent to:
   747  //
   748  //	var r = regexp.MustCompile(`^/[^/.]+\.[^/]+/[^/.]+$`)
   749  //
   750  //	func rpcNameIsTRPCForm(s string) bool {
   751  //		return r.MatchString(s)
   752  //	}
   753  //
   754  // But regexp is much slower than the current version.
   755  // Refer to BenchmarkRPCNameIsTRPCForm in message_bench_test.go.
   756  func rpcNameIsTRPCForm(s string) bool {
   757  	if len(s) == 0 {
   758  		return false
   759  	}
   760  	if s[0] != '/' { // ^/
   761  		return false
   762  	}
   763  	const start = 1
   764  	firstDot := strings.Index(s[start:], ".")
   765  	if firstDot == -1 || firstDot == 0 { // [^.]+\.
   766  		return false
   767  	}
   768  	if strings.Contains(s[start:start+firstDot], "/") { // [^/]+\.
   769  		return false
   770  	}
   771  	secondSlash := strings.Index(s[start+firstDot:], "/")
   772  	if secondSlash == -1 || secondSlash == 1 { // [^/]+/
   773  		return false
   774  	}
   775  	if start+firstDot+secondSlash == len(s)-1 { // The second slash should not be the last character.
   776  		return false
   777  	}
   778  	const offset = 1
   779  	if strings.ContainsAny(s[start+firstDot+secondSlash+offset:], "/.") { // [^/.]+$
   780  		return false
   781  	}
   782  	return true
   783  }