<commit_before>package air

import (
	"strings"
	"unsafe"
)

// router is a registry of all registered routes.
type router struct {
	tree      *node
	maxParams int
	routes    map[string]struct{}
}

// theRouter is the singleton of the `router`.
var theRouter = &router{
	tree: &node{
		handlers: map[string]Handler{},
	},
	routes: map[string]struct{}{},
}

// register registers a new route for the method and the path with the matching
// h in the r with the optional route-level gases..
func (r *router) register(method, path string, h Handler, gases ...Gas) {
	if path != "/" && hasLastSlash(path) {
		path = path[:len(path)-1]
	}

	msg := ""
	if path == "" {
		msg = "air: route path cannot be empty"
	} else if path[0] != '/' {
		msg = "air: route path must start with /"
	} else if strings.Contains(path, "//") {
		msg = "air: route path cannot have //"
	} else if strings.Count(path, ":") > 1 {
		ps := strings.Split(path, "/")
		for _, p := range ps {
			if strings.Count(p, ":") > 1 {
				msg = "air: adjacent params in route path " +
					"must be separated by /"
				break
			}
		}
	} else if strings.Contains(path, "*") {
		if strings.Count(path, "*") > 1 {
			msg = "air: only one * is allowed in route path"
		} else if path[len(path)-1] != '*' {
			msg = "air: * can only appear at end of route path"
		} else if strings.Contains(
			path[strings.LastIndex(path, "/"):],
			":",
		) {
			msg = "air: adjacent param and * in route path must " +
				"be separated by /"
		}
	} else if _, ok := r.routes[method+pathWithoutParamNames(path)]; ok {
		msg = "air: route already exists"
	} else {
		r.routes[method+pathWithoutParamNames(path)] = struct{}{}
	}

	if msg != "" {
		FATAL(msg, map[string]interface{}{
			"route": map[string]interface{}{
				"method": method,
				"path":   path,
			},
		})
	}

	nh := func(req *Request, res *Response) error {
		h := h
		for i := len(gases) - 1; i >= 0; i-- {
			h = gases[i](h)
		}

		return h(req, res)
	}

	paramNames := []string{}

	for i, l := 0, len(path); i < l; i++ {
		if path[i] == ':' {
			j := i + 1

			r.insert(method, path[:i], nil, static, nil)

			for ; i < l && path[i] != '/'; i++ {
			}

			paramName := path[j:i]

			for _, pn := range paramNames {
				if pn == paramName {
					e := map[string]interface{}{
						"route": map[string]interface{}{
							"method": method,
							"path":   path,
						},
					}
					FATAL(
						"air: route path cannot have "+
							"duplicate param names",
						e,
					)
				}
			}<commit_msg>refactor: panic if registering an invalid route<commit_after>package air

import (
	"strings"
	"unsafe"
)

// router is a registry of all registered routes.
type router struct {
	tree      *node
	maxParams int
	routes    map[string]struct{}
}

// theRouter is the singleton of the `router`.
var theRouter = &router{
	tree: &node{
		handlers: map[string]Handler{},
	},
	routes: map[string]struct{}{},
}

// register registers a new route for the method and the path with the matching
// h in the r with the optional route-level gases..
func (r *router) register(method, path string, h Handler, gases ...Gas) {
	if path != "/" && hasLastSlash(path) {
		path = path[:len(path)-1]
	}

	msg := ""
	if path == "" {
		msg = "air: route path cannot be empty"
	} else if path[0] != '/' {
		msg = "air: route path must start with /"
	} else if strings.Contains(path, "//") {
		msg = "air: route path cannot have //"
	} else if strings.Count(path, ":") > 1 {
		ps := strings.Split(path, "/")
		for _, p := range ps {
			if strings.Count(p, ":") > 1 {
				msg = "air: adjacent params in route path " +
					"must be separated by /"
				break
			}
		}
	} else if strings.Contains(path, "*") {
		if strings.Count(path, "*") > 1 {
			msg = "air: only one * is allowed in route path"
		} else if path[len(path)-1] != '*' {
			msg = "air: * can only appear at end of route path"
		} else if strings.Contains(
			path[strings.LastIndex(path, "/"):],
			":",
		) {
			msg = "air: adjacent param and * in route path must " +
				"be separated by /"
		}
	} else if _, ok := r.routes[method+pathWithoutParamNames(path)]; ok {
		msg = "air: route already exists"
	} else {
		r.routes[method+pathWithoutParamNames(path)] = struct{}{}
	}

	if msg != "" {
		panic(msg)
	}

	paramNames := []string{}
	nh := func(req *Request, res *Response) error {
		h := h
		for i := len(gases) - 1; i >= 0; i-- {
			h = gases[i](h)
		}

		return h(req, res)
	}

	for i, l := 0, len(path); i < l; i++ {
		if path[i] == ':' {
			j := i + 1

			r.insert(method, path[:i], nil, static, nil)

			for ; i < l && path[i] != '/'; i++ {
			}

			paramName := path[j:i]

			for _, pn := range paramNames {
				if pn == paramName {
					panic("air: route path cannot have " +
						"duplicate param names")
				}
			}
{'fraction_non_alphanumeric': 0.17316561844863732, 'fraction_numerical': 0.0041928721174004195, 'mean_word_length': 2.7099533437014, 'pattern_counts': {'":': 12, '<': 7, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6452613', 'n_tokens_mistral': 1948, 'n_tokens_neox': 1690, 'n_words': 533}