func (n *node) addRoute(path string, function *FunctionDescriptor) {
	fullPath := path
	n.priority++
	if n.path == "" && n.indices == "" {
		n.insertChild(path, fullPath, function)
		n.nType = root
		return
	}
walk:
	for {
		i := longestCommonPrefix(path, n.path)
		if i < len(n.path) {
			child := node{
				path:      n.path[i:],
				wildChild: n.wildChild,
				nType:     static,
				indices:   n.indices,
				children:  n.children,
				function:  n.function,
				priority:  n.priority - 1,
			}
			n.children = []*node{&child}
			n.indices = string([]byte{n.path[i]})
			n.path = path[:i]
			n.function = nil
			n.wildChild = false
		}
		if i < len(path) {
			path = path[i:]
			if n.wildChild {
				n = n.children[0]
				n.priority++
				if len(path) >= len(n.path) && n.path == path[:len(n.path)] &&
					n.nType != catchAll &&
					(len(n.path) >= len(path) || path[len(n.path)] == '/') {
					continue walk
				} else {
					pathSeg := path
					if n.nType != catchAll {
						pathSeg = strings.SplitN(pathSeg, "/", 2)[0]
					}
					prefix := fullPath[:strings.Index(fullPath, pathSeg)] + n.path
					panic("'" + pathSeg +
						"' in new path '" + fullPath +
						"' conflicts with existing wildcard '" + n.path +
						"' in existing prefix '" + prefix +
						"'")
				}
			}
			idxc := path[0]
			if n.nType == param && idxc == '/' && len(n.children) == 1 {
				n = n.children[0]
				n.priority++
				continue walk
			}
			for i, c := range []byte(n.indices) {
				if c == idxc {
					i = n.incrementChildPrio(i)
					n = n.children[i]
					continue walk
				}
			}
			if idxc != ':' && idxc != '*' {
				n.indices += string([]byte{idxc})
				child := &node{}
				n.children = append(n.children, child)
				n.incrementChildPrio(len(n.indices) - 1)
				n = child
			}
			n.insertChild(path, fullPath, function)
			return
		}
		if n.function != nil {
			panic("a function is already registered for path '" + fullPath + "'")
		}
		n.function = function
		return
	}
}
addRoute adds a node with the given function to the path.
Not concurrency-safe!
package descriptor
import (
	"strings"
)
func min(a, b int) int {
	if a <= b {
		return a
	}
	return b
}
func longestCommonPrefix(a, b string) int {
	i := 0
	max := min(len(a), len(b))
	for i < max && a[i] == b[i] {
		i++
	}
	return i
}
func findWildcard(path string) (wilcard string, i int, valid bool) {
	for start, c := range []byte(path) {
		if c != ':' && c != '*' {
			continue
		}
		valid = true
		for end, c := range []byte(path[start+1:]) {
			switch c {
			case '/':
				return path[start : start+1+end], start, valid
			case ':', '*':
				valid = false
			}
		}
		return path[start:], start, valid
	}
	return "", -1, false
}
func countParams(path string) uint16 {
	var n uint
	for i := range []byte(path) {
		switch path[i] {
		case ':', '*':
			n++
		}
	}
	return uint16(n)
}
type nodeType uint8
const (
	static nodeType = iota  
	root
	param
	catchAll
)
type node struct {
	path      string
	indices   string
	wildChild bool
	nType     nodeType
	priority  uint32
	children  []*node
	function  *FunctionDescriptor
}
func (n *node) incrementChildPrio(pos int) int {
	cs := n.children
	cs[pos].priority++
	prio := cs[pos].priority
	newPos := pos
	for ; newPos > 0 && cs[newPos-1].priority < prio; newPos-- {
		cs[newPos-1], cs[newPos] = cs[newPos], cs[newPos-1]
	}
	if newPos != pos {
		n.indices = n.indices[:newPos] +  
			n.indices[pos:pos+1] +  
			n.indices[newPos:pos] + n.indices[pos+1:]  
	}
	return newPos
}