81 lines
1.6 KiB
Go
81 lines
1.6 KiB
Go
/*
|
|
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
|
|
*
|
|
* This work is published and licensed under a Creative Commons
|
|
* Attribution-NonCommercial-NoDerivatives 4.0 International License.
|
|
*
|
|
* Distribution of this work is permitted, but commercial use and
|
|
* modifications are strictly prohibited.
|
|
*/
|
|
package router
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
const (
|
|
compContextPlain int = iota
|
|
compContextRegex
|
|
|
|
startRegex byte = '{'
|
|
stopRegex byte = '}'
|
|
)
|
|
|
|
func pathCompiler(path string) (string, error) {
|
|
var err error
|
|
res := make([]byte, 0)
|
|
var pos int = compContextPlain
|
|
var depth int = 0
|
|
pattern := make([]byte, 0)
|
|
for _, b := range []byte(path) {
|
|
switch pos {
|
|
case compContextPlain:
|
|
switch b {
|
|
case stopRegex:
|
|
depth -= 1
|
|
res = append(res, b)
|
|
case startRegex:
|
|
depth += 1
|
|
pos = compContextRegex // pattern started
|
|
pattern = make([]byte, 0)
|
|
default:
|
|
res = append(res, b)
|
|
}
|
|
case compContextRegex:
|
|
switch b {
|
|
case startRegex:
|
|
depth += 1
|
|
case stopRegex:
|
|
depth -= 1
|
|
if depth == 0 {
|
|
pattern = convertRegexp(pattern)
|
|
res = append(res, pattern...)
|
|
pos = compContextPlain // pattern ended
|
|
}
|
|
default:
|
|
pattern = append(pattern, b)
|
|
}
|
|
}
|
|
}
|
|
if depth != 0 {
|
|
err = fmt.Errorf("Unbalanced brackets into pattern")
|
|
}
|
|
return string(res), err
|
|
}
|
|
|
|
const (
|
|
defaultRegexp = `[a-zA-Z0-9_\.][/\-\.a-zA-Z0-9_%%=:~]+`
|
|
)
|
|
|
|
func convertRegexp(src []byte) []byte {
|
|
var res string
|
|
const patternSeps = ":"
|
|
parts := strings.SplitN(string(src), patternSeps, 2)
|
|
if len(parts) == 1 {
|
|
parts = append(parts, defaultRegexp)
|
|
}
|
|
res = fmt.Sprintf("(?<%s>%s)", parts[0], parts[1])
|
|
return []byte(res)
|
|
}
|