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 }