summaryrefslogtreecommitdiff
path: root/pathrouter/choice.go
diff options
context:
space:
mode:
authorStefan Majewsky <majewsky@gmx.net>2026-06-27 22:34:36 +0200
committerStefan Majewsky <majewsky@gmx.net>2026-06-27 22:34:36 +0200
commit8e9889d3e5b2874854832d1d882d124132546f49 (patch)
tree80ab6bf53dac3090630ad58d7ebfbbf2c97019ca /pathrouter/choice.go
parent8804729561d8e5edd7179f494d89c620459d319f (diff)
downloadgo-gg-8e9889d3e5b2874854832d1d882d124132546f49.tar.gz
add package pathrouter
Diffstat (limited to 'pathrouter/choice.go')
-rw-r--r--pathrouter/choice.go61
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
+ },
+ }
+}