gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

compile.go (2370B)


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