glide up
This commit is contained in:
		
							
								
								
									
										117
									
								
								vendor/github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway/httprule/compile.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								vendor/github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway/httprule/compile.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,117 @@
 | 
			
		||||
package httprule
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/grpc-ecosystem/grpc-gateway/utilities"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	opcodeVersion = 1
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Template is a compiled representation of path templates.
 | 
			
		||||
type Template struct {
 | 
			
		||||
	// Version is the version number of the format.
 | 
			
		||||
	Version int
 | 
			
		||||
	// OpCodes is a sequence of operations.
 | 
			
		||||
	OpCodes []int
 | 
			
		||||
	// Pool is a constant pool
 | 
			
		||||
	Pool []string
 | 
			
		||||
	// Verb is a VERB part in the template.
 | 
			
		||||
	Verb string
 | 
			
		||||
	// Fields is a list of field paths bound in this template.
 | 
			
		||||
	Fields []string
 | 
			
		||||
	// Original template (example: /v1/a_bit_of_everything)
 | 
			
		||||
	Template string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Compiler compiles utilities representation of path templates into marshallable operations.
 | 
			
		||||
// They can be unmarshalled by runtime.NewPattern.
 | 
			
		||||
type Compiler interface {
 | 
			
		||||
	Compile() Template
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type op struct {
 | 
			
		||||
	// code is the opcode of the operation
 | 
			
		||||
	code utilities.OpCode
 | 
			
		||||
 | 
			
		||||
	// str is a string operand of the code.
 | 
			
		||||
	// num is ignored if str is not empty.
 | 
			
		||||
	str string
 | 
			
		||||
 | 
			
		||||
	// num is a numeric operand of the code.
 | 
			
		||||
	num int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (w wildcard) compile() []op {
 | 
			
		||||
	return []op{
 | 
			
		||||
		{code: utilities.OpPush},
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (w deepWildcard) compile() []op {
 | 
			
		||||
	return []op{
 | 
			
		||||
		{code: utilities.OpPushM},
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (l literal) compile() []op {
 | 
			
		||||
	return []op{
 | 
			
		||||
		{
 | 
			
		||||
			code: utilities.OpLitPush,
 | 
			
		||||
			str:  string(l),
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (v variable) compile() []op {
 | 
			
		||||
	var ops []op
 | 
			
		||||
	for _, s := range v.segments {
 | 
			
		||||
		ops = append(ops, s.compile()...)
 | 
			
		||||
	}
 | 
			
		||||
	ops = append(ops, op{
 | 
			
		||||
		code: utilities.OpConcatN,
 | 
			
		||||
		num:  len(v.segments),
 | 
			
		||||
	}, op{
 | 
			
		||||
		code: utilities.OpCapture,
 | 
			
		||||
		str:  v.path,
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	return ops
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (t template) Compile() Template {
 | 
			
		||||
	var rawOps []op
 | 
			
		||||
	for _, s := range t.segments {
 | 
			
		||||
		rawOps = append(rawOps, s.compile()...)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var (
 | 
			
		||||
		ops    []int
 | 
			
		||||
		pool   []string
 | 
			
		||||
		fields []string
 | 
			
		||||
	)
 | 
			
		||||
	consts := make(map[string]int)
 | 
			
		||||
	for _, op := range rawOps {
 | 
			
		||||
		ops = append(ops, int(op.code))
 | 
			
		||||
		if op.str == "" {
 | 
			
		||||
			ops = append(ops, op.num)
 | 
			
		||||
		} else {
 | 
			
		||||
			if _, ok := consts[op.str]; !ok {
 | 
			
		||||
				consts[op.str] = len(pool)
 | 
			
		||||
				pool = append(pool, op.str)
 | 
			
		||||
			}
 | 
			
		||||
			ops = append(ops, consts[op.str])
 | 
			
		||||
		}
 | 
			
		||||
		if op.code == utilities.OpCapture {
 | 
			
		||||
			fields = append(fields, op.str)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return Template{
 | 
			
		||||
		Version:  opcodeVersion,
 | 
			
		||||
		OpCodes:  ops,
 | 
			
		||||
		Pool:     pool,
 | 
			
		||||
		Verb:     t.verb,
 | 
			
		||||
		Fields:   fields,
 | 
			
		||||
		Template: t.template,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										122
									
								
								vendor/github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway/httprule/compile_test.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										122
									
								
								vendor/github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway/httprule/compile_test.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,122 @@
 | 
			
		||||
package httprule
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/grpc-ecosystem/grpc-gateway/utilities"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	operandFiller = 0
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestCompile(t *testing.T) {
 | 
			
		||||
	for _, spec := range []struct {
 | 
			
		||||
		segs []segment
 | 
			
		||||
		verb string
 | 
			
		||||
 | 
			
		||||
		ops    []int
 | 
			
		||||
		pool   []string
 | 
			
		||||
		fields []string
 | 
			
		||||
	}{
 | 
			
		||||
		{},
 | 
			
		||||
		{
 | 
			
		||||
			segs: []segment{
 | 
			
		||||
				wildcard{},
 | 
			
		||||
			},
 | 
			
		||||
			ops: []int{int(utilities.OpPush), operandFiller},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			segs: []segment{
 | 
			
		||||
				deepWildcard{},
 | 
			
		||||
			},
 | 
			
		||||
			ops: []int{int(utilities.OpPushM), operandFiller},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			segs: []segment{
 | 
			
		||||
				literal("v1"),
 | 
			
		||||
			},
 | 
			
		||||
			ops:  []int{int(utilities.OpLitPush), 0},
 | 
			
		||||
			pool: []string{"v1"},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			segs: []segment{
 | 
			
		||||
				literal("v1"),
 | 
			
		||||
			},
 | 
			
		||||
			verb: "LOCK",
 | 
			
		||||
			ops:  []int{int(utilities.OpLitPush), 0},
 | 
			
		||||
			pool: []string{"v1"},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			segs: []segment{
 | 
			
		||||
				variable{
 | 
			
		||||
					path: "name.nested",
 | 
			
		||||
					segments: []segment{
 | 
			
		||||
						wildcard{},
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			ops: []int{
 | 
			
		||||
				int(utilities.OpPush), operandFiller,
 | 
			
		||||
				int(utilities.OpConcatN), 1,
 | 
			
		||||
				int(utilities.OpCapture), 0,
 | 
			
		||||
			},
 | 
			
		||||
			pool:   []string{"name.nested"},
 | 
			
		||||
			fields: []string{"name.nested"},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			segs: []segment{
 | 
			
		||||
				literal("obj"),
 | 
			
		||||
				variable{
 | 
			
		||||
					path: "name.nested",
 | 
			
		||||
					segments: []segment{
 | 
			
		||||
						literal("a"),
 | 
			
		||||
						wildcard{},
 | 
			
		||||
						literal("b"),
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
				variable{
 | 
			
		||||
					path: "obj",
 | 
			
		||||
					segments: []segment{
 | 
			
		||||
						deepWildcard{},
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			ops: []int{
 | 
			
		||||
				int(utilities.OpLitPush), 0,
 | 
			
		||||
				int(utilities.OpLitPush), 1,
 | 
			
		||||
				int(utilities.OpPush), operandFiller,
 | 
			
		||||
				int(utilities.OpLitPush), 2,
 | 
			
		||||
				int(utilities.OpConcatN), 3,
 | 
			
		||||
				int(utilities.OpCapture), 3,
 | 
			
		||||
				int(utilities.OpPushM), operandFiller,
 | 
			
		||||
				int(utilities.OpConcatN), 1,
 | 
			
		||||
				int(utilities.OpCapture), 0,
 | 
			
		||||
			},
 | 
			
		||||
			pool:   []string{"obj", "a", "b", "name.nested"},
 | 
			
		||||
			fields: []string{"name.nested", "obj"},
 | 
			
		||||
		},
 | 
			
		||||
	} {
 | 
			
		||||
		tmpl := template{
 | 
			
		||||
			segments: spec.segs,
 | 
			
		||||
			verb:     spec.verb,
 | 
			
		||||
		}
 | 
			
		||||
		compiled := tmpl.Compile()
 | 
			
		||||
		if got, want := compiled.Version, opcodeVersion; got != want {
 | 
			
		||||
			t.Errorf("tmpl.Compile().Version = %d; want %d; segs=%#v, verb=%q", got, want, spec.segs, spec.verb)
 | 
			
		||||
		}
 | 
			
		||||
		if got, want := compiled.OpCodes, spec.ops; !reflect.DeepEqual(got, want) {
 | 
			
		||||
			t.Errorf("tmpl.Compile().OpCodes = %v; want %v; segs=%#v, verb=%q", got, want, spec.segs, spec.verb)
 | 
			
		||||
		}
 | 
			
		||||
		if got, want := compiled.Pool, spec.pool; !reflect.DeepEqual(got, want) {
 | 
			
		||||
			t.Errorf("tmpl.Compile().Pool = %q; want %q; segs=%#v, verb=%q", got, want, spec.segs, spec.verb)
 | 
			
		||||
		}
 | 
			
		||||
		if got, want := compiled.Verb, spec.verb; got != want {
 | 
			
		||||
			t.Errorf("tmpl.Compile().Verb = %q; want %q; segs=%#v, verb=%q", got, want, spec.segs, spec.verb)
 | 
			
		||||
		}
 | 
			
		||||
		if got, want := compiled.Fields, spec.fields; !reflect.DeepEqual(got, want) {
 | 
			
		||||
			t.Errorf("tmpl.Compile().Fields = %q; want %q; segs=%#v, verb=%q", got, want, spec.segs, spec.verb)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										351
									
								
								vendor/github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway/httprule/parse.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										351
									
								
								vendor/github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway/httprule/parse.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,351 @@
 | 
			
		||||
package httprule
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"github.com/golang/glog"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// InvalidTemplateError indicates that the path template is not valid.
 | 
			
		||||
type InvalidTemplateError struct {
 | 
			
		||||
	tmpl string
 | 
			
		||||
	msg  string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e InvalidTemplateError) Error() string {
 | 
			
		||||
	return fmt.Sprintf("%s: %s", e.msg, e.tmpl)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Parse parses the string representation of path template
 | 
			
		||||
func Parse(tmpl string) (Compiler, error) {
 | 
			
		||||
	if !strings.HasPrefix(tmpl, "/") {
 | 
			
		||||
		return template{}, InvalidTemplateError{tmpl: tmpl, msg: "no leading /"}
 | 
			
		||||
	}
 | 
			
		||||
	tokens, verb := tokenize(tmpl[1:])
 | 
			
		||||
 | 
			
		||||
	p := parser{tokens: tokens}
 | 
			
		||||
	segs, err := p.topLevelSegments()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return template{}, InvalidTemplateError{tmpl: tmpl, msg: err.Error()}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return template{
 | 
			
		||||
		segments: segs,
 | 
			
		||||
		verb:     verb,
 | 
			
		||||
		template: tmpl,
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func tokenize(path string) (tokens []string, verb string) {
 | 
			
		||||
	if path == "" {
 | 
			
		||||
		return []string{eof}, ""
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	const (
 | 
			
		||||
		init = iota
 | 
			
		||||
		field
 | 
			
		||||
		nested
 | 
			
		||||
	)
 | 
			
		||||
	var (
 | 
			
		||||
		st = init
 | 
			
		||||
	)
 | 
			
		||||
	for path != "" {
 | 
			
		||||
		var idx int
 | 
			
		||||
		switch st {
 | 
			
		||||
		case init:
 | 
			
		||||
			idx = strings.IndexAny(path, "/{")
 | 
			
		||||
		case field:
 | 
			
		||||
			idx = strings.IndexAny(path, ".=}")
 | 
			
		||||
		case nested:
 | 
			
		||||
			idx = strings.IndexAny(path, "/}")
 | 
			
		||||
		}
 | 
			
		||||
		if idx < 0 {
 | 
			
		||||
			tokens = append(tokens, path)
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
		switch r := path[idx]; r {
 | 
			
		||||
		case '/', '.':
 | 
			
		||||
		case '{':
 | 
			
		||||
			st = field
 | 
			
		||||
		case '=':
 | 
			
		||||
			st = nested
 | 
			
		||||
		case '}':
 | 
			
		||||
			st = init
 | 
			
		||||
		}
 | 
			
		||||
		if idx == 0 {
 | 
			
		||||
			tokens = append(tokens, path[idx:idx+1])
 | 
			
		||||
		} else {
 | 
			
		||||
			tokens = append(tokens, path[:idx], path[idx:idx+1])
 | 
			
		||||
		}
 | 
			
		||||
		path = path[idx+1:]
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	l := len(tokens)
 | 
			
		||||
	t := tokens[l-1]
 | 
			
		||||
	if idx := strings.LastIndex(t, ":"); idx == 0 {
 | 
			
		||||
		tokens, verb = tokens[:l-1], t[1:]
 | 
			
		||||
	} else if idx > 0 {
 | 
			
		||||
		tokens[l-1], verb = t[:idx], t[idx+1:]
 | 
			
		||||
	}
 | 
			
		||||
	tokens = append(tokens, eof)
 | 
			
		||||
	return tokens, verb
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// parser is a parser of the template syntax defined in github.com/googleapis/googleapis/google/api/http.proto.
 | 
			
		||||
type parser struct {
 | 
			
		||||
	tokens   []string
 | 
			
		||||
	accepted []string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// topLevelSegments is the target of this parser.
 | 
			
		||||
func (p *parser) topLevelSegments() ([]segment, error) {
 | 
			
		||||
	glog.V(1).Infof("Parsing %q", p.tokens)
 | 
			
		||||
	segs, err := p.segments()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	glog.V(2).Infof("accept segments: %q; %q", p.accepted, p.tokens)
 | 
			
		||||
	if _, err := p.accept(typeEOF); err != nil {
 | 
			
		||||
		return nil, fmt.Errorf("unexpected token %q after segments %q", p.tokens[0], strings.Join(p.accepted, ""))
 | 
			
		||||
	}
 | 
			
		||||
	glog.V(2).Infof("accept eof: %q; %q", p.accepted, p.tokens)
 | 
			
		||||
	return segs, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *parser) segments() ([]segment, error) {
 | 
			
		||||
	s, err := p.segment()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	glog.V(2).Infof("accept segment: %q; %q", p.accepted, p.tokens)
 | 
			
		||||
 | 
			
		||||
	segs := []segment{s}
 | 
			
		||||
	for {
 | 
			
		||||
		if _, err := p.accept("/"); err != nil {
 | 
			
		||||
			return segs, nil
 | 
			
		||||
		}
 | 
			
		||||
		s, err := p.segment()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return segs, err
 | 
			
		||||
		}
 | 
			
		||||
		segs = append(segs, s)
 | 
			
		||||
		glog.V(2).Infof("accept segment: %q; %q", p.accepted, p.tokens)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *parser) segment() (segment, error) {
 | 
			
		||||
	if _, err := p.accept("*"); err == nil {
 | 
			
		||||
		return wildcard{}, nil
 | 
			
		||||
	}
 | 
			
		||||
	if _, err := p.accept("**"); err == nil {
 | 
			
		||||
		return deepWildcard{}, nil
 | 
			
		||||
	}
 | 
			
		||||
	if l, err := p.literal(); err == nil {
 | 
			
		||||
		return l, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	v, err := p.variable()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, fmt.Errorf("segment neither wildcards, literal or variable: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	return v, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *parser) literal() (segment, error) {
 | 
			
		||||
	lit, err := p.accept(typeLiteral)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return literal(lit), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *parser) variable() (segment, error) {
 | 
			
		||||
	if _, err := p.accept("{"); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	path, err := p.fieldPath()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var segs []segment
 | 
			
		||||
	if _, err := p.accept("="); err == nil {
 | 
			
		||||
		segs, err = p.segments()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, fmt.Errorf("invalid segment in variable %q: %v", path, err)
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		segs = []segment{wildcard{}}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if _, err := p.accept("}"); err != nil {
 | 
			
		||||
		return nil, fmt.Errorf("unterminated variable segment: %s", path)
 | 
			
		||||
	}
 | 
			
		||||
	return variable{
 | 
			
		||||
		path:     path,
 | 
			
		||||
		segments: segs,
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *parser) fieldPath() (string, error) {
 | 
			
		||||
	c, err := p.accept(typeIdent)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
	components := []string{c}
 | 
			
		||||
	for {
 | 
			
		||||
		if _, err = p.accept("."); err != nil {
 | 
			
		||||
			return strings.Join(components, "."), nil
 | 
			
		||||
		}
 | 
			
		||||
		c, err := p.accept(typeIdent)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return "", fmt.Errorf("invalid field path component: %v", err)
 | 
			
		||||
		}
 | 
			
		||||
		components = append(components, c)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// A termType is a type of terminal symbols.
 | 
			
		||||
type termType string
 | 
			
		||||
 | 
			
		||||
// These constants define some of valid values of termType.
 | 
			
		||||
// They improve readability of parse functions.
 | 
			
		||||
//
 | 
			
		||||
// You can also use "/", "*", "**", "." or "=" as valid values.
 | 
			
		||||
const (
 | 
			
		||||
	typeIdent   = termType("ident")
 | 
			
		||||
	typeLiteral = termType("literal")
 | 
			
		||||
	typeEOF     = termType("$")
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	// eof is the terminal symbol which always appears at the end of token sequence.
 | 
			
		||||
	eof = "\u0000"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// accept tries to accept a token in "p".
 | 
			
		||||
// This function consumes a token and returns it if it matches to the specified "term".
 | 
			
		||||
// If it doesn't match, the function does not consume any tokens and return an error.
 | 
			
		||||
func (p *parser) accept(term termType) (string, error) {
 | 
			
		||||
	t := p.tokens[0]
 | 
			
		||||
	switch term {
 | 
			
		||||
	case "/", "*", "**", ".", "=", "{", "}":
 | 
			
		||||
		if t != string(term) {
 | 
			
		||||
			return "", fmt.Errorf("expected %q but got %q", term, t)
 | 
			
		||||
		}
 | 
			
		||||
	case typeEOF:
 | 
			
		||||
		if t != eof {
 | 
			
		||||
			return "", fmt.Errorf("expected EOF but got %q", t)
 | 
			
		||||
		}
 | 
			
		||||
	case typeIdent:
 | 
			
		||||
		if err := expectIdent(t); err != nil {
 | 
			
		||||
			return "", err
 | 
			
		||||
		}
 | 
			
		||||
	case typeLiteral:
 | 
			
		||||
		if err := expectPChars(t); err != nil {
 | 
			
		||||
			return "", err
 | 
			
		||||
		}
 | 
			
		||||
	default:
 | 
			
		||||
		return "", fmt.Errorf("unknown termType %q", term)
 | 
			
		||||
	}
 | 
			
		||||
	p.tokens = p.tokens[1:]
 | 
			
		||||
	p.accepted = append(p.accepted, t)
 | 
			
		||||
	return t, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// expectPChars determines if "t" consists of only pchars defined in RFC3986.
 | 
			
		||||
//
 | 
			
		||||
// https://www.ietf.org/rfc/rfc3986.txt, P.49
 | 
			
		||||
//   pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"
 | 
			
		||||
//   unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
 | 
			
		||||
//   sub-delims    = "!" / "$" / "&" / "'" / "(" / ")"
 | 
			
		||||
//                 / "*" / "+" / "," / ";" / "="
 | 
			
		||||
//   pct-encoded   = "%" HEXDIG HEXDIG
 | 
			
		||||
func expectPChars(t string) error {
 | 
			
		||||
	const (
 | 
			
		||||
		init = iota
 | 
			
		||||
		pct1
 | 
			
		||||
		pct2
 | 
			
		||||
	)
 | 
			
		||||
	st := init
 | 
			
		||||
	for _, r := range t {
 | 
			
		||||
		if st != init {
 | 
			
		||||
			if !isHexDigit(r) {
 | 
			
		||||
				return fmt.Errorf("invalid hexdigit: %c(%U)", r, r)
 | 
			
		||||
			}
 | 
			
		||||
			switch st {
 | 
			
		||||
			case pct1:
 | 
			
		||||
				st = pct2
 | 
			
		||||
			case pct2:
 | 
			
		||||
				st = init
 | 
			
		||||
			}
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// unreserved
 | 
			
		||||
		switch {
 | 
			
		||||
		case 'A' <= r && r <= 'Z':
 | 
			
		||||
			continue
 | 
			
		||||
		case 'a' <= r && r <= 'z':
 | 
			
		||||
			continue
 | 
			
		||||
		case '0' <= r && r <= '9':
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		switch r {
 | 
			
		||||
		case '-', '.', '_', '~':
 | 
			
		||||
			// unreserved
 | 
			
		||||
		case '!', '$', '&', '\'', '(', ')', '*', '+', ',', ';', '=':
 | 
			
		||||
			// sub-delims
 | 
			
		||||
		case ':', '@':
 | 
			
		||||
			// rest of pchar
 | 
			
		||||
		case '%':
 | 
			
		||||
			// pct-encoded
 | 
			
		||||
			st = pct1
 | 
			
		||||
		default:
 | 
			
		||||
			return fmt.Errorf("invalid character in path segment: %q(%U)", r, r)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if st != init {
 | 
			
		||||
		return fmt.Errorf("invalid percent-encoding in %q", t)
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// expectIdent determines if "ident" is a valid identifier in .proto schema ([[:alpha:]_][[:alphanum:]_]*).
 | 
			
		||||
func expectIdent(ident string) error {
 | 
			
		||||
	if ident == "" {
 | 
			
		||||
		return fmt.Errorf("empty identifier")
 | 
			
		||||
	}
 | 
			
		||||
	for pos, r := range ident {
 | 
			
		||||
		switch {
 | 
			
		||||
		case '0' <= r && r <= '9':
 | 
			
		||||
			if pos == 0 {
 | 
			
		||||
				return fmt.Errorf("identifier starting with digit: %s", ident)
 | 
			
		||||
			}
 | 
			
		||||
			continue
 | 
			
		||||
		case 'A' <= r && r <= 'Z':
 | 
			
		||||
			continue
 | 
			
		||||
		case 'a' <= r && r <= 'z':
 | 
			
		||||
			continue
 | 
			
		||||
		case r == '_':
 | 
			
		||||
			continue
 | 
			
		||||
		default:
 | 
			
		||||
			return fmt.Errorf("invalid character %q(%U) in identifier: %s", r, r, ident)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func isHexDigit(r rune) bool {
 | 
			
		||||
	switch {
 | 
			
		||||
	case '0' <= r && r <= '9':
 | 
			
		||||
		return true
 | 
			
		||||
	case 'A' <= r && r <= 'F':
 | 
			
		||||
		return true
 | 
			
		||||
	case 'a' <= r && r <= 'f':
 | 
			
		||||
		return true
 | 
			
		||||
	}
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										313
									
								
								vendor/github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway/httprule/parse_test.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										313
									
								
								vendor/github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway/httprule/parse_test.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,313 @@
 | 
			
		||||
package httprule
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"flag"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/golang/glog"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestTokenize(t *testing.T) {
 | 
			
		||||
	for _, spec := range []struct {
 | 
			
		||||
		src    string
 | 
			
		||||
		tokens []string
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			src:    "",
 | 
			
		||||
			tokens: []string{eof},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			src:    "v1",
 | 
			
		||||
			tokens: []string{"v1", eof},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			src:    "v1/b",
 | 
			
		||||
			tokens: []string{"v1", "/", "b", eof},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			src:    "v1/endpoint/*",
 | 
			
		||||
			tokens: []string{"v1", "/", "endpoint", "/", "*", eof},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			src:    "v1/endpoint/**",
 | 
			
		||||
			tokens: []string{"v1", "/", "endpoint", "/", "**", eof},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			src: "v1/b/{bucket_name=*}",
 | 
			
		||||
			tokens: []string{
 | 
			
		||||
				"v1", "/",
 | 
			
		||||
				"b", "/",
 | 
			
		||||
				"{", "bucket_name", "=", "*", "}",
 | 
			
		||||
				eof,
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			src: "v1/b/{bucket_name=buckets/*}",
 | 
			
		||||
			tokens: []string{
 | 
			
		||||
				"v1", "/",
 | 
			
		||||
				"b", "/",
 | 
			
		||||
				"{", "bucket_name", "=", "buckets", "/", "*", "}",
 | 
			
		||||
				eof,
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			src: "v1/b/{bucket_name=buckets/*}/o",
 | 
			
		||||
			tokens: []string{
 | 
			
		||||
				"v1", "/",
 | 
			
		||||
				"b", "/",
 | 
			
		||||
				"{", "bucket_name", "=", "buckets", "/", "*", "}", "/",
 | 
			
		||||
				"o",
 | 
			
		||||
				eof,
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			src: "v1/b/{bucket_name=buckets/*}/o/{name}",
 | 
			
		||||
			tokens: []string{
 | 
			
		||||
				"v1", "/",
 | 
			
		||||
				"b", "/",
 | 
			
		||||
				"{", "bucket_name", "=", "buckets", "/", "*", "}", "/",
 | 
			
		||||
				"o", "/", "{", "name", "}",
 | 
			
		||||
				eof,
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			src: "v1/a=b&c=d;e=f:g/endpoint.rdf",
 | 
			
		||||
			tokens: []string{
 | 
			
		||||
				"v1", "/",
 | 
			
		||||
				"a=b&c=d;e=f:g", "/",
 | 
			
		||||
				"endpoint.rdf",
 | 
			
		||||
				eof,
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	} {
 | 
			
		||||
		tokens, verb := tokenize(spec.src)
 | 
			
		||||
		if got, want := tokens, spec.tokens; !reflect.DeepEqual(got, want) {
 | 
			
		||||
			t.Errorf("tokenize(%q) = %q, _; want %q, _", spec.src, got, want)
 | 
			
		||||
		}
 | 
			
		||||
		if got, want := verb, ""; got != want {
 | 
			
		||||
			t.Errorf("tokenize(%q) = _, %q; want _, %q", spec.src, got, want)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		src := fmt.Sprintf("%s:%s", spec.src, "LOCK")
 | 
			
		||||
		tokens, verb = tokenize(src)
 | 
			
		||||
		if got, want := tokens, spec.tokens; !reflect.DeepEqual(got, want) {
 | 
			
		||||
			t.Errorf("tokenize(%q) = %q, _; want %q, _", src, got, want)
 | 
			
		||||
		}
 | 
			
		||||
		if got, want := verb, "LOCK"; got != want {
 | 
			
		||||
			t.Errorf("tokenize(%q) = _, %q; want _, %q", src, got, want)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestParseSegments(t *testing.T) {
 | 
			
		||||
	flag.Set("v", "3")
 | 
			
		||||
	for _, spec := range []struct {
 | 
			
		||||
		tokens []string
 | 
			
		||||
		want   []segment
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			tokens: []string{"v1", eof},
 | 
			
		||||
			want: []segment{
 | 
			
		||||
				literal("v1"),
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			tokens: []string{"-._~!$&'()*+,;=:@", eof},
 | 
			
		||||
			want: []segment{
 | 
			
		||||
				literal("-._~!$&'()*+,;=:@"),
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			tokens: []string{"%e7%ac%ac%e4%b8%80%e7%89%88", eof},
 | 
			
		||||
			want: []segment{
 | 
			
		||||
				literal("%e7%ac%ac%e4%b8%80%e7%89%88"),
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			tokens: []string{"v1", "/", "*", eof},
 | 
			
		||||
			want: []segment{
 | 
			
		||||
				literal("v1"),
 | 
			
		||||
				wildcard{},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			tokens: []string{"v1", "/", "**", eof},
 | 
			
		||||
			want: []segment{
 | 
			
		||||
				literal("v1"),
 | 
			
		||||
				deepWildcard{},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			tokens: []string{"{", "name", "}", eof},
 | 
			
		||||
			want: []segment{
 | 
			
		||||
				variable{
 | 
			
		||||
					path: "name",
 | 
			
		||||
					segments: []segment{
 | 
			
		||||
						wildcard{},
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			tokens: []string{"{", "name", "=", "*", "}", eof},
 | 
			
		||||
			want: []segment{
 | 
			
		||||
				variable{
 | 
			
		||||
					path: "name",
 | 
			
		||||
					segments: []segment{
 | 
			
		||||
						wildcard{},
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			tokens: []string{"{", "field", ".", "nested", ".", "nested2", "=", "*", "}", eof},
 | 
			
		||||
			want: []segment{
 | 
			
		||||
				variable{
 | 
			
		||||
					path: "field.nested.nested2",
 | 
			
		||||
					segments: []segment{
 | 
			
		||||
						wildcard{},
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			tokens: []string{"{", "name", "=", "a", "/", "b", "/", "*", "}", eof},
 | 
			
		||||
			want: []segment{
 | 
			
		||||
				variable{
 | 
			
		||||
					path: "name",
 | 
			
		||||
					segments: []segment{
 | 
			
		||||
						literal("a"),
 | 
			
		||||
						literal("b"),
 | 
			
		||||
						wildcard{},
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			tokens: []string{
 | 
			
		||||
				"v1", "/",
 | 
			
		||||
				"{",
 | 
			
		||||
				"name", ".", "nested", ".", "nested2",
 | 
			
		||||
				"=",
 | 
			
		||||
				"a", "/", "b", "/", "*",
 | 
			
		||||
				"}", "/",
 | 
			
		||||
				"o", "/",
 | 
			
		||||
				"{",
 | 
			
		||||
				"another_name",
 | 
			
		||||
				"=",
 | 
			
		||||
				"a", "/", "b", "/", "*", "/", "c",
 | 
			
		||||
				"}", "/",
 | 
			
		||||
				"**",
 | 
			
		||||
				eof},
 | 
			
		||||
			want: []segment{
 | 
			
		||||
				literal("v1"),
 | 
			
		||||
				variable{
 | 
			
		||||
					path: "name.nested.nested2",
 | 
			
		||||
					segments: []segment{
 | 
			
		||||
						literal("a"),
 | 
			
		||||
						literal("b"),
 | 
			
		||||
						wildcard{},
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
				literal("o"),
 | 
			
		||||
				variable{
 | 
			
		||||
					path: "another_name",
 | 
			
		||||
					segments: []segment{
 | 
			
		||||
						literal("a"),
 | 
			
		||||
						literal("b"),
 | 
			
		||||
						wildcard{},
 | 
			
		||||
						literal("c"),
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
				deepWildcard{},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	} {
 | 
			
		||||
		p := parser{tokens: spec.tokens}
 | 
			
		||||
		segs, err := p.topLevelSegments()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			t.Errorf("parser{%q}.segments() failed with %v; want success", spec.tokens, err)
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		if got, want := segs, spec.want; !reflect.DeepEqual(got, want) {
 | 
			
		||||
			t.Errorf("parser{%q}.segments() = %#v; want %#v", spec.tokens, got, want)
 | 
			
		||||
		}
 | 
			
		||||
		if got := p.tokens; len(got) > 0 {
 | 
			
		||||
			t.Errorf("p.tokens = %q; want []; spec.tokens=%q", got, spec.tokens)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestParseSegmentsWithErrors(t *testing.T) {
 | 
			
		||||
	flag.Set("v", "3")
 | 
			
		||||
	for _, spec := range []struct {
 | 
			
		||||
		tokens []string
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			// double slash
 | 
			
		||||
			tokens: []string{"/", eof},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			// invalid literal
 | 
			
		||||
			tokens: []string{"a?b", eof},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			// invalid percent-encoding
 | 
			
		||||
			tokens: []string{"%", eof},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			// invalid percent-encoding
 | 
			
		||||
			tokens: []string{"%2", eof},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			// invalid percent-encoding
 | 
			
		||||
			tokens: []string{"a%2z", eof},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			// empty segments
 | 
			
		||||
			tokens: []string{eof},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			// unterminated variable
 | 
			
		||||
			tokens: []string{"{", "name", eof},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			// unterminated variable
 | 
			
		||||
			tokens: []string{"{", "name", "=", eof},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			// unterminated variable
 | 
			
		||||
			tokens: []string{"{", "name", "=", "*", eof},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			// empty component in field path
 | 
			
		||||
			tokens: []string{"{", "name", ".", "}", eof},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			// empty component in field path
 | 
			
		||||
			tokens: []string{"{", "name", ".", ".", "nested", "}", eof},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			// invalid character in identifier
 | 
			
		||||
			tokens: []string{"{", "field-name", "}", eof},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			// no slash between segments
 | 
			
		||||
			tokens: []string{"v1", "endpoint", eof},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			// no slash between segments
 | 
			
		||||
			tokens: []string{"v1", "{", "name", "}", eof},
 | 
			
		||||
		},
 | 
			
		||||
	} {
 | 
			
		||||
		p := parser{tokens: spec.tokens}
 | 
			
		||||
		segs, err := p.topLevelSegments()
 | 
			
		||||
		if err == nil {
 | 
			
		||||
			t.Errorf("parser{%q}.segments() succeeded; want InvalidTemplateError; accepted %#v", spec.tokens, segs)
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		glog.V(1).Info(err)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										60
									
								
								vendor/github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway/httprule/types.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								vendor/github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway/httprule/types.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,60 @@
 | 
			
		||||
package httprule
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type template struct {
 | 
			
		||||
	segments []segment
 | 
			
		||||
	verb     string
 | 
			
		||||
	template string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type segment interface {
 | 
			
		||||
	fmt.Stringer
 | 
			
		||||
	compile() (ops []op)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type wildcard struct{}
 | 
			
		||||
 | 
			
		||||
type deepWildcard struct{}
 | 
			
		||||
 | 
			
		||||
type literal string
 | 
			
		||||
 | 
			
		||||
type variable struct {
 | 
			
		||||
	path     string
 | 
			
		||||
	segments []segment
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (wildcard) String() string {
 | 
			
		||||
	return "*"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (deepWildcard) String() string {
 | 
			
		||||
	return "**"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (l literal) String() string {
 | 
			
		||||
	return string(l)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (v variable) String() string {
 | 
			
		||||
	var segs []string
 | 
			
		||||
	for _, s := range v.segments {
 | 
			
		||||
		segs = append(segs, s.String())
 | 
			
		||||
	}
 | 
			
		||||
	return fmt.Sprintf("{%s=%s}", v.path, strings.Join(segs, "/"))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (t template) String() string {
 | 
			
		||||
	var segs []string
 | 
			
		||||
	for _, s := range t.segments {
 | 
			
		||||
		segs = append(segs, s.String())
 | 
			
		||||
	}
 | 
			
		||||
	str := strings.Join(segs, "/")
 | 
			
		||||
	if t.verb != "" {
 | 
			
		||||
		str = fmt.Sprintf("%s:%s", str, t.verb)
 | 
			
		||||
	}
 | 
			
		||||
	return "/" + str
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										91
									
								
								vendor/github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway/httprule/types_test.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								vendor/github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway/httprule/types_test.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,91 @@
 | 
			
		||||
package httprule
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"testing"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestTemplateStringer(t *testing.T) {
 | 
			
		||||
	for _, spec := range []struct {
 | 
			
		||||
		segs []segment
 | 
			
		||||
		want string
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			segs: []segment{
 | 
			
		||||
				literal("v1"),
 | 
			
		||||
			},
 | 
			
		||||
			want: "/v1",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			segs: []segment{
 | 
			
		||||
				wildcard{},
 | 
			
		||||
			},
 | 
			
		||||
			want: "/*",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			segs: []segment{
 | 
			
		||||
				deepWildcard{},
 | 
			
		||||
			},
 | 
			
		||||
			want: "/**",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			segs: []segment{
 | 
			
		||||
				variable{
 | 
			
		||||
					path: "name",
 | 
			
		||||
					segments: []segment{
 | 
			
		||||
						literal("a"),
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			want: "/{name=a}",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			segs: []segment{
 | 
			
		||||
				variable{
 | 
			
		||||
					path: "name",
 | 
			
		||||
					segments: []segment{
 | 
			
		||||
						literal("a"),
 | 
			
		||||
						wildcard{},
 | 
			
		||||
						literal("b"),
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			want: "/{name=a/*/b}",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			segs: []segment{
 | 
			
		||||
				literal("v1"),
 | 
			
		||||
				variable{
 | 
			
		||||
					path: "name",
 | 
			
		||||
					segments: []segment{
 | 
			
		||||
						literal("a"),
 | 
			
		||||
						wildcard{},
 | 
			
		||||
						literal("b"),
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
				literal("c"),
 | 
			
		||||
				variable{
 | 
			
		||||
					path: "field.nested",
 | 
			
		||||
					segments: []segment{
 | 
			
		||||
						wildcard{},
 | 
			
		||||
						literal("d"),
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
				wildcard{},
 | 
			
		||||
				literal("e"),
 | 
			
		||||
				deepWildcard{},
 | 
			
		||||
			},
 | 
			
		||||
			want: "/v1/{name=a/*/b}/c/{field.nested=*/d}/*/e/**",
 | 
			
		||||
		},
 | 
			
		||||
	} {
 | 
			
		||||
		tmpl := template{segments: spec.segs}
 | 
			
		||||
		if got, want := tmpl.String(), spec.want; got != want {
 | 
			
		||||
			t.Errorf("%#v.String() = %q; want %q", tmpl, got, want)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		tmpl.verb = "LOCK"
 | 
			
		||||
		if got, want := tmpl.String(), fmt.Sprintf("%s:LOCK", spec.want); got != want {
 | 
			
		||||
			t.Errorf("%#v.String() = %q; want %q", tmpl, got, want)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user