github.com/btccom/go-micro/v2@v2.9.3/api/router/util/compile.go (about)

     1  package util
     2  
     3  // download from https://raw.githubusercontent.com/grpc-ecosystem/grpc-gateway/master/protoc-gen-grpc-gateway/httprule/compile.go
     4  
     5  const (
     6  	opcodeVersion = 1
     7  )
     8  
     9  // Template is a compiled representation of path templates.
    10  type Template struct {
    11  	// Version is the version number of the format.
    12  	Version int
    13  	// OpCodes is a sequence of operations.
    14  	OpCodes []int
    15  	// Pool is a constant pool
    16  	Pool []string
    17  	// Verb is a VERB part in the template.
    18  	Verb string
    19  	// Fields is a list of field paths bound in this template.
    20  	Fields []string
    21  	// Original template (example: /v1/a_bit_of_everything)
    22  	Template string
    23  }
    24  
    25  // Compiler compiles utilities representation of path templates into marshallable operations.
    26  // They can be unmarshalled by runtime.NewPattern.
    27  type Compiler interface {
    28  	Compile() Template
    29  }
    30  
    31  type op struct {
    32  	// code is the opcode of the operation
    33  	code OpCode
    34  
    35  	// str is a string operand of the code.
    36  	// operand is ignored if str is not empty.
    37  	str string
    38  
    39  	// operand is a numeric operand of the code.
    40  	operand int
    41  }
    42  
    43  func (w wildcard) compile() []op {
    44  	return []op{
    45  		{code: OpPush},
    46  	}
    47  }
    48  
    49  func (w deepWildcard) compile() []op {
    50  	return []op{
    51  		{code: OpPushM},
    52  	}
    53  }
    54  
    55  func (l literal) compile() []op {
    56  	return []op{
    57  		{
    58  			code: OpLitPush,
    59  			str:  string(l),
    60  		},
    61  	}
    62  }
    63  
    64  func (v variable) compile() []op {
    65  	var ops []op
    66  	for _, s := range v.segments {
    67  		ops = append(ops, s.compile()...)
    68  	}
    69  	ops = append(ops, op{
    70  		code:    OpConcatN,
    71  		operand: len(v.segments),
    72  	}, op{
    73  		code: OpCapture,
    74  		str:  v.path,
    75  	})
    76  
    77  	return ops
    78  }
    79  
    80  func (t template) Compile() Template {
    81  	var rawOps []op
    82  	for _, s := range t.segments {
    83  		rawOps = append(rawOps, s.compile()...)
    84  	}
    85  
    86  	var (
    87  		ops    []int
    88  		pool   []string
    89  		fields []string
    90  	)
    91  	consts := make(map[string]int)
    92  	for _, op := range rawOps {
    93  		ops = append(ops, int(op.code))
    94  		if op.str == "" {
    95  			ops = append(ops, op.operand)
    96  		} else {
    97  			if _, ok := consts[op.str]; !ok {
    98  				consts[op.str] = len(pool)
    99  				pool = append(pool, op.str)
   100  			}
   101  			ops = append(ops, consts[op.str])
   102  		}
   103  		if op.code == OpCapture {
   104  			fields = append(fields, op.str)
   105  		}
   106  	}
   107  	return Template{
   108  		Version:  opcodeVersion,
   109  		OpCodes:  ops,
   110  		Pool:     pool,
   111  		Verb:     t.verb,
   112  		Fields:   fields,
   113  		Template: t.template,
   114  	}
   115  }