diff options
| author | Stefan Majewsky <majewsky@gmx.net> | 2026-06-27 22:34:36 +0200 |
|---|---|---|
| committer | Stefan Majewsky <majewsky@gmx.net> | 2026-06-27 22:34:36 +0200 |
| commit | 8e9889d3e5b2874854832d1d882d124132546f49 (patch) | |
| tree | 80ab6bf53dac3090630ad58d7ebfbbf2c97019ca /pathrouter/choice.go | |
| parent | 8804729561d8e5edd7179f494d89c620459d319f (diff) | |
| download | go-gg-8e9889d3e5b2874854832d1d882d124132546f49.tar.gz | |
add package pathrouter
Diffstat (limited to 'pathrouter/choice.go')
| -rw-r--r-- | pathrouter/choice.go | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/pathrouter/choice.go b/pathrouter/choice.go new file mode 100644 index 0000000..09026b8 --- /dev/null +++ b/pathrouter/choice.go @@ -0,0 +1,61 @@ +// SPDX-FileCopyrightText: 2026 Stefan Majewsky <majewsky@gmx.net> +// SPDX-License-Identifier: Apache-2.0 + +package pathrouter + +import ( + "slices" + + . "go.xyrillian.de/gg/option" + "go.xyrillian.de/gg/options" +) + +// Choice is a [Matcher] that accepts all subpaths that are accepted by any of its contained matchers. +// If multiple matchers accept the requested subpath, the first match wins. +// +// Choice is used to specify different matchers for different subpaths, +// as illustrated in the example in the package docstring. +func Choice(matchers ...Matcher) Matcher { + downcasted := make([]realMatcher, len(matchers)) + for idx, matcher := range matchers { + downcasted[idx] = matcher.downcast() + } + return choice(downcasted) +} + +func choice(matchers []realMatcher) Matcher { + if len(matchers) == 0 { + panic("Choice() called without any matchers") + } + + var ( + minLengths = make([]int, len(matchers)) + maxLengths = make([]Option[int], len(matchers)) + maxLengthIsInf = false + ) + for idx, m := range matchers { + minLengths[idx] = m.minLength + maxLengths[idx] = m.maxLength + if m.maxLength.IsNone() { + maxLengthIsInf = true + } + } + maxLength := None[int]() + if !maxLengthIsInf { + maxLength = options.Max(maxLengths...) + } + + return realMatcher{ + minLength: slices.Min(minLengths), + maxLength: maxLength, + accept: func(path []string, vars map[string]string) HandlerFunc { + for _, m := range matchers { + hf := m.accept(path, vars) + if hf != nil { + return hf + } + } + return nil + }, + } +} |
