diff options
author | 2025-03-09 17:47:56 +0100 | |
---|---|---|
committer | 2025-03-10 01:59:49 +0100 | |
commit | 3ac1ee16f377d31a0fb80c8dae28b6239ac4229e (patch) | |
tree | f61faa581feaaeaba2542b9f2b8234a590684413 /vendor/github.com/go-openapi/runtime/middleware/denco/router.go | |
parent | [chore] update URLs to forked source (diff) | |
download | gotosocial-3ac1ee16f377d31a0fb80c8dae28b6239ac4229e.tar.xz |
[chore] remove vendor
Diffstat (limited to 'vendor/github.com/go-openapi/runtime/middleware/denco/router.go')
-rw-r--r-- | vendor/github.com/go-openapi/runtime/middleware/denco/router.go | 467 |
1 files changed, 0 insertions, 467 deletions
diff --git a/vendor/github.com/go-openapi/runtime/middleware/denco/router.go b/vendor/github.com/go-openapi/runtime/middleware/denco/router.go deleted file mode 100644 index 4377f77a4..000000000 --- a/vendor/github.com/go-openapi/runtime/middleware/denco/router.go +++ /dev/null @@ -1,467 +0,0 @@ -// Package denco provides fast URL router. -package denco - -import ( - "errors" - "fmt" - "sort" - "strings" -) - -const ( - // ParamCharacter is a special character for path parameter. - ParamCharacter = ':' - - // WildcardCharacter is a special character for wildcard path parameter. - WildcardCharacter = '*' - - // TerminationCharacter is a special character for end of path. - TerminationCharacter = '#' - - // SeparatorCharacter separates path segments. - SeparatorCharacter = '/' - - // PathParamCharacter indicates a RESTCONF path param - PathParamCharacter = '=' - - // MaxSize is max size of records and internal slice. - MaxSize = (1 << 22) - 1 -) - -// Router represents a URL router. -type Router struct { - param *doubleArray - // SizeHint expects the maximum number of path parameters in records to Build. - // SizeHint will be used to determine the capacity of the memory to allocate. - // By default, SizeHint will be determined from given records to Build. - SizeHint int - - static map[string]interface{} -} - -// New returns a new Router. -func New() *Router { - return &Router{ - SizeHint: -1, - static: make(map[string]interface{}), - param: newDoubleArray(), - } -} - -// Lookup returns data and path parameters that associated with path. -// params is a slice of the Param that arranged in the order in which parameters appeared. -// e.g. when built routing path is "/path/to/:id/:name" and given path is "/path/to/1/alice". params order is [{"id": "1"}, {"name": "alice"}], not [{"name": "alice"}, {"id": "1"}]. -func (rt *Router) Lookup(path string) (data interface{}, params Params, found bool) { - if data, found = rt.static[path]; found { - return data, nil, true - } - if len(rt.param.node) == 1 { - return nil, nil, false - } - nd, params, found := rt.param.lookup(path, make([]Param, 0, rt.SizeHint), 1) - if !found { - return nil, nil, false - } - for i := 0; i < len(params); i++ { - params[i].Name = nd.paramNames[i] - } - return nd.data, params, true -} - -// Build builds URL router from records. -func (rt *Router) Build(records []Record) error { - statics, params := makeRecords(records) - if len(params) > MaxSize { - return errors.New("denco: too many records") - } - if rt.SizeHint < 0 { - rt.SizeHint = 0 - for _, p := range params { - size := 0 - for _, k := range p.Key { - if k == ParamCharacter || k == WildcardCharacter { - size++ - } - } - if size > rt.SizeHint { - rt.SizeHint = size - } - } - } - for _, r := range statics { - rt.static[r.Key] = r.Value - } - if err := rt.param.build(params, 1, 0, make(map[int]struct{})); err != nil { - return err - } - return nil -} - -// Param represents name and value of path parameter. -type Param struct { - Name string - Value string -} - -// Params represents the name and value of path parameters. -type Params []Param - -// Get gets the first value associated with the given name. -// If there are no values associated with the key, Get returns "". -func (ps Params) Get(name string) string { - for _, p := range ps { - if p.Name == name { - return p.Value - } - } - return "" -} - -type doubleArray struct { - bc []baseCheck - node []*node -} - -func newDoubleArray() *doubleArray { - return &doubleArray{ - bc: []baseCheck{0}, - node: []*node{nil}, // A start index is adjusting to 1 because 0 will be used as a mark of non-existent node. - } -} - -// baseCheck contains BASE, CHECK and Extra flags. -// From the top, 22bits of BASE, 2bits of Extra flags and 8bits of CHECK. -// -// BASE (22bit) | Extra flags (2bit) | CHECK (8bit) -// -// |----------------------|--|--------| -// 32 10 8 0 -type baseCheck uint32 - -func (bc baseCheck) Base() int { - return int(bc >> 10) -} - -func (bc *baseCheck) SetBase(base int) { - *bc |= baseCheck(base) << 10 -} - -func (bc baseCheck) Check() byte { - return byte(bc) -} - -func (bc *baseCheck) SetCheck(check byte) { - *bc |= baseCheck(check) -} - -func (bc baseCheck) IsEmpty() bool { - return bc&0xfffffcff == 0 -} - -func (bc baseCheck) IsSingleParam() bool { - return bc¶mTypeSingle == paramTypeSingle -} - -func (bc baseCheck) IsWildcardParam() bool { - return bc¶mTypeWildcard == paramTypeWildcard -} - -func (bc baseCheck) IsAnyParam() bool { - return bc¶mTypeAny != 0 -} - -func (bc *baseCheck) SetSingleParam() { - *bc |= (1 << 8) -} - -func (bc *baseCheck) SetWildcardParam() { - *bc |= (1 << 9) -} - -const ( - paramTypeSingle = 0x0100 - paramTypeWildcard = 0x0200 - paramTypeAny = 0x0300 -) - -func (da *doubleArray) lookup(path string, params []Param, idx int) (*node, []Param, bool) { - indices := make([]uint64, 0, 1) - for i := 0; i < len(path); i++ { - if da.bc[idx].IsAnyParam() { - indices = append(indices, (uint64(i)<<32)|(uint64(idx)&0xffffffff)) - } - c := path[i] - if idx = nextIndex(da.bc[idx].Base(), c); idx >= len(da.bc) || da.bc[idx].Check() != c { - goto BACKTRACKING - } - } - if next := nextIndex(da.bc[idx].Base(), TerminationCharacter); next < len(da.bc) && da.bc[next].Check() == TerminationCharacter { - return da.node[da.bc[next].Base()], params, true - } - -BACKTRACKING: - for j := len(indices) - 1; j >= 0; j-- { - i, idx := int(indices[j]>>32), int(indices[j]&0xffffffff) - if da.bc[idx].IsSingleParam() { - nextIdx := nextIndex(da.bc[idx].Base(), ParamCharacter) - if nextIdx >= len(da.bc) { - break - } - - next := NextSeparator(path, i) - nextParams := params - nextParams = append(nextParams, Param{Value: path[i:next]}) - if nd, nextNextParams, found := da.lookup(path[next:], nextParams, nextIdx); found { - return nd, nextNextParams, true - } - } - - if da.bc[idx].IsWildcardParam() { - nextIdx := nextIndex(da.bc[idx].Base(), WildcardCharacter) - nextParams := params - nextParams = append(nextParams, Param{Value: path[i:]}) - return da.node[da.bc[nextIdx].Base()], nextParams, true - } - } - return nil, nil, false -} - -// build builds double-array from records. -func (da *doubleArray) build(srcs []*record, idx, depth int, usedBase map[int]struct{}) error { - sort.Stable(recordSlice(srcs)) - base, siblings, leaf, err := da.arrange(srcs, idx, depth, usedBase) - if err != nil { - return err - } - if leaf != nil { - nd, err := makeNode(leaf) - if err != nil { - return err - } - da.bc[idx].SetBase(len(da.node)) - da.node = append(da.node, nd) - } - for _, sib := range siblings { - da.setCheck(nextIndex(base, sib.c), sib.c) - } - for _, sib := range siblings { - records := srcs[sib.start:sib.end] - switch sib.c { - case ParamCharacter: - for _, r := range records { - next := NextSeparator(r.Key, depth+1) - name := r.Key[depth+1 : next] - r.paramNames = append(r.paramNames, name) - r.Key = r.Key[next:] - } - da.bc[idx].SetSingleParam() - if err := da.build(records, nextIndex(base, sib.c), 0, usedBase); err != nil { - return err - } - case WildcardCharacter: - r := records[0] - name := r.Key[depth+1 : len(r.Key)-1] - r.paramNames = append(r.paramNames, name) - r.Key = "" - da.bc[idx].SetWildcardParam() - if err := da.build(records, nextIndex(base, sib.c), 0, usedBase); err != nil { - return err - } - default: - if err := da.build(records, nextIndex(base, sib.c), depth+1, usedBase); err != nil { - return err - } - } - } - return nil -} - -// setBase sets BASE. -func (da *doubleArray) setBase(i, base int) { - da.bc[i].SetBase(base) -} - -// setCheck sets CHECK. -func (da *doubleArray) setCheck(i int, check byte) { - da.bc[i].SetCheck(check) -} - -// findEmptyIndex returns an index of unused BASE/CHECK node. -func (da *doubleArray) findEmptyIndex(start int) int { - i := start - for ; i < len(da.bc); i++ { - if da.bc[i].IsEmpty() { - break - } - } - return i -} - -// findBase returns good BASE. -func (da *doubleArray) findBase(siblings []sibling, start int, usedBase map[int]struct{}) (base int) { - for idx, firstChar := start+1, siblings[0].c; ; idx = da.findEmptyIndex(idx + 1) { - base = nextIndex(idx, firstChar) - if _, used := usedBase[base]; used { - continue - } - i := 0 - for ; i < len(siblings); i++ { - next := nextIndex(base, siblings[i].c) - if len(da.bc) <= next { - da.bc = append(da.bc, make([]baseCheck, next-len(da.bc)+1)...) - } - if !da.bc[next].IsEmpty() { - break - } - } - if i == len(siblings) { - break - } - } - usedBase[base] = struct{}{} - return base -} - -func (da *doubleArray) arrange(records []*record, idx, depth int, usedBase map[int]struct{}) (base int, siblings []sibling, leaf *record, err error) { - siblings, leaf, err = makeSiblings(records, depth) - if err != nil { - return -1, nil, nil, err - } - if len(siblings) < 1 { - return -1, nil, leaf, nil - } - base = da.findBase(siblings, idx, usedBase) - if base > MaxSize { - return -1, nil, nil, errors.New("denco: too many elements of internal slice") - } - da.setBase(idx, base) - return base, siblings, leaf, err -} - -// node represents a node of Double-Array. -type node struct { - data interface{} - - // Names of path parameters. - paramNames []string -} - -// makeNode returns a new node from record. -func makeNode(r *record) (*node, error) { - dups := make(map[string]bool) - for _, name := range r.paramNames { - if dups[name] { - return nil, fmt.Errorf("denco: path parameter `%v' is duplicated in the key `%v'", name, r.Key) - } - dups[name] = true - } - return &node{data: r.Value, paramNames: r.paramNames}, nil -} - -// sibling represents an intermediate data of build for Double-Array. -type sibling struct { - // An index of start of duplicated characters. - start int - - // An index of end of duplicated characters. - end int - - // A character of sibling. - c byte -} - -// nextIndex returns a next index of array of BASE/CHECK. -func nextIndex(base int, c byte) int { - return base ^ int(c) -} - -// makeSiblings returns slice of sibling. -func makeSiblings(records []*record, depth int) (sib []sibling, leaf *record, err error) { - var ( - pc byte - n int - ) - for i, r := range records { - if len(r.Key) <= depth { - leaf = r - continue - } - c := r.Key[depth] - switch { - case pc < c: - sib = append(sib, sibling{start: i, c: c}) - case pc == c: - continue - default: - return nil, nil, errors.New("denco: BUG: routing table hasn't been sorted") - } - if n > 0 { - sib[n-1].end = i - } - pc = c - n++ - } - if n == 0 { - return nil, leaf, nil - } - sib[n-1].end = len(records) - return sib, leaf, nil -} - -// Record represents a record data for router construction. -type Record struct { - // Key for router construction. - Key string - - // Result value for Key. - Value interface{} -} - -// NewRecord returns a new Record. -func NewRecord(key string, value interface{}) Record { - return Record{ - Key: key, - Value: value, - } -} - -// record represents a record that use to build the Double-Array. -type record struct { - Record - paramNames []string -} - -// makeRecords returns the records that use to build Double-Arrays. -func makeRecords(srcs []Record) (statics, params []*record) { - termChar := string(TerminationCharacter) - paramPrefix := string(SeparatorCharacter) + string(ParamCharacter) - wildcardPrefix := string(SeparatorCharacter) + string(WildcardCharacter) - restconfPrefix := string(PathParamCharacter) + string(ParamCharacter) - for _, r := range srcs { - if strings.Contains(r.Key, paramPrefix) || strings.Contains(r.Key, wildcardPrefix) || strings.Contains(r.Key, restconfPrefix) { - r.Key += termChar - params = append(params, &record{Record: r}) - } else { - statics = append(statics, &record{Record: r}) - } - } - return statics, params -} - -// recordSlice represents a slice of Record for sort and implements the sort.Interface. -type recordSlice []*record - -// Len implements the sort.Interface.Len. -func (rs recordSlice) Len() int { - return len(rs) -} - -// Less implements the sort.Interface.Less. -func (rs recordSlice) Less(i, j int) bool { - return rs[i].Key < rs[j].Key -} - -// Swap implements the sort.Interface.Swap. -func (rs recordSlice) Swap(i, j int) { - rs[i], rs[j] = rs[j], rs[i] -} |