Compare commits
3 Commits
cfdd687bb7
...
1bd1a884c4
Author | SHA1 | Date | |
---|---|---|---|
1bd1a884c4 | |||
872fd98c14 | |||
20089847c2 |
|
@ -21,8 +21,8 @@ router.Add("GET", "/hello", "...")
|
||||||
router.Add("GET", "/world", "...")
|
router.Add("GET", "/world", "...")
|
||||||
|
|
||||||
// Parameter routes
|
// Parameter routes
|
||||||
router.Add("GET", "/users/:id", "...")
|
router.Add("GET", "/users/[id]", "...")
|
||||||
router.Add("GET", "/users/:id/comments", "...")
|
router.Add("GET", "/users/[id]/comments", "...")
|
||||||
|
|
||||||
// Wildcard routes
|
// Wildcard routes
|
||||||
router.Add("GET", "/images/*path", "...")
|
router.Add("GET", "/images/*path", "...")
|
||||||
|
|
9
flow.go
9
flow.go
|
@ -1,9 +0,0 @@
|
||||||
package router
|
|
||||||
|
|
||||||
type Flow int
|
|
||||||
|
|
||||||
const (
|
|
||||||
flowStop Flow = iota
|
|
||||||
flowBegin
|
|
||||||
flowNext
|
|
||||||
)
|
|
|
@ -5,17 +5,17 @@ import "strings"
|
||||||
// Node types
|
// Node types
|
||||||
const (
|
const (
|
||||||
separator = '/'
|
separator = '/'
|
||||||
parameter = ':'
|
parameter = '['
|
||||||
wildcard = '*'
|
wildcard = '*'
|
||||||
)
|
)
|
||||||
|
|
||||||
// A node on our radix tree
|
// A node on our radix tree
|
||||||
type TreeNode[T any] struct {
|
type Node[T any] struct {
|
||||||
prefix string
|
prefix string
|
||||||
data T
|
data T
|
||||||
children []*TreeNode[T]
|
children []*Node[T]
|
||||||
parameter *TreeNode[T]
|
parameter *Node[T]
|
||||||
wildcard *TreeNode[T]
|
wildcard *Node[T]
|
||||||
indexes []uint8
|
indexes []uint8
|
||||||
start uint8
|
start uint8
|
||||||
end uint8
|
end uint8
|
||||||
|
@ -26,7 +26,7 @@ type TreeNode[T any] struct {
|
||||||
// node with the given path and data. If path is empty, it will
|
// node with the given path and data. If path is empty, it will
|
||||||
// not create another child node and instead assign the data
|
// not create another child node and instead assign the data
|
||||||
// directly to the node.
|
// directly to the node.
|
||||||
func (node *TreeNode[T]) split(index int, path string, data T) {
|
func (node *Node[T]) split(index int, path string, data T) {
|
||||||
// Create split node with the remaining string
|
// Create split node with the remaining string
|
||||||
splitNode := node.clone(node.prefix[index:])
|
splitNode := node.clone(node.prefix[index:])
|
||||||
|
|
||||||
|
@ -48,8 +48,8 @@ func (node *TreeNode[T]) split(index int, path string, data T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clone the node with a new prefix
|
// Clone the node with a new prefix
|
||||||
func (node *TreeNode[T]) clone(prefix string) *TreeNode[T] {
|
func (node *Node[T]) clone(prefix string) *Node[T] {
|
||||||
return &TreeNode[T]{
|
return &Node[T]{
|
||||||
prefix: prefix,
|
prefix: prefix,
|
||||||
data: node.data,
|
data: node.data,
|
||||||
children: node.children,
|
children: node.children,
|
||||||
|
@ -63,7 +63,7 @@ func (node *TreeNode[T]) clone(prefix string) *TreeNode[T] {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset the node, set the prefix
|
// Reset the node, set the prefix
|
||||||
func (node *TreeNode[T]) reset(prefix string) {
|
func (node *Node[T]) reset(prefix string) {
|
||||||
var empty T
|
var empty T
|
||||||
node.prefix = prefix
|
node.prefix = prefix
|
||||||
node.data = empty
|
node.data = empty
|
||||||
|
@ -77,7 +77,7 @@ func (node *TreeNode[T]) reset(prefix string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Append the given path to the tree
|
// Append the given path to the tree
|
||||||
func (node *TreeNode[T]) append(path string, data T) {
|
func (node *Node[T]) append(path string, data T) {
|
||||||
// At this point, all we know is that somewhere
|
// At this point, all we know is that somewhere
|
||||||
// in the remaining string we have parameters.
|
// in the remaining string we have parameters.
|
||||||
// node: /user|
|
// node: /user|
|
||||||
|
@ -106,7 +106,7 @@ func (node *TreeNode[T]) append(path string, data T) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
child := &TreeNode[T]{
|
child := &Node[T]{
|
||||||
prefix: path,
|
prefix: path,
|
||||||
data: data,
|
data: data,
|
||||||
}
|
}
|
||||||
|
@ -119,15 +119,21 @@ func (node *TreeNode[T]) append(path string, data T) {
|
||||||
// If we're directly in front of a parameter,
|
// If we're directly in front of a parameter,
|
||||||
// add a parameter node.
|
// add a parameter node.
|
||||||
if paramStart == 0 {
|
if paramStart == 0 {
|
||||||
paramEnd := strings.IndexByte(path, separator)
|
paramEnd := strings.IndexByte(path[1:], ']')
|
||||||
|
|
||||||
if paramEnd == -1 {
|
if paramEnd == -1 {
|
||||||
paramEnd = len(path)
|
paramEnd = len(path)
|
||||||
|
} else {
|
||||||
|
paramEnd = paramEnd + 1 // Account for the offset from path[1:]
|
||||||
}
|
}
|
||||||
|
|
||||||
child := &TreeNode[T]{
|
nextSep := strings.IndexByte(path[paramEnd+1:], separator)
|
||||||
prefix: path[1:paramEnd],
|
if nextSep == -1 {
|
||||||
kind: path[paramStart],
|
nextSep = len(path[paramEnd+1:])
|
||||||
|
}
|
||||||
|
|
||||||
|
child := &Node[T]{
|
||||||
|
prefix: path[1:paramEnd], // Exclude the opening '['
|
||||||
|
kind: parameter,
|
||||||
}
|
}
|
||||||
|
|
||||||
switch child.kind {
|
switch child.kind {
|
||||||
|
@ -135,7 +141,7 @@ func (node *TreeNode[T]) append(path string, data T) {
|
||||||
child.addTrailingSlash(data)
|
child.addTrailingSlash(data)
|
||||||
node.parameter = child
|
node.parameter = child
|
||||||
node = child
|
node = child
|
||||||
path = path[paramEnd:]
|
path = path[paramEnd+nextSep+1:]
|
||||||
continue
|
continue
|
||||||
|
|
||||||
case wildcard:
|
case wildcard:
|
||||||
|
@ -156,7 +162,7 @@ func (node *TreeNode[T]) append(path string, data T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a normal node with the path before the parameter start.
|
// Add a normal node with the path before the parameter start.
|
||||||
child := &TreeNode[T]{
|
child := &Node[T]{
|
||||||
prefix: path[:paramStart],
|
prefix: path[:paramStart],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,7 +179,7 @@ func (node *TreeNode[T]) append(path string, data T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a child tree node
|
// Add a child tree node
|
||||||
func (node *TreeNode[T]) addChild(child *TreeNode[T]) {
|
func (node *Node[T]) addChild(child *Node[T]) {
|
||||||
if len(node.children) == 0 {
|
if len(node.children) == 0 {
|
||||||
node.children = append(node.children, nil)
|
node.children = append(node.children, nil)
|
||||||
}
|
}
|
||||||
|
@ -213,19 +219,19 @@ func (node *TreeNode[T]) addChild(child *TreeNode[T]) {
|
||||||
node.children[index] = child
|
node.children[index] = child
|
||||||
}
|
}
|
||||||
|
|
||||||
func (node *TreeNode[T]) addTrailingSlash(data T) {
|
func (node *Node[T]) addTrailingSlash(data T) {
|
||||||
if strings.HasSuffix(node.prefix, "/") || node.kind == wildcard || (separator >= node.start && separator < node.end && node.indexes[separator-node.start] != 0) {
|
if strings.HasSuffix(node.prefix, "/") || node.kind == wildcard || (separator >= node.start && separator < node.end && node.indexes[separator-node.start] != 0) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
node.addChild(&TreeNode[T]{
|
node.addChild(&Node[T]{
|
||||||
prefix: "/",
|
prefix: "/",
|
||||||
data: data,
|
data: data,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Traverses the tree and calls the given function on every node.
|
// Traverses the tree and calls the given function on every node.
|
||||||
func (node *TreeNode[T]) each(callback func(*TreeNode[T])) {
|
func (node *Node[T]) each(callback func(*Node[T])) {
|
||||||
callback(node)
|
callback(node)
|
||||||
|
|
||||||
for _, child := range node.children {
|
for _, child := range node.children {
|
||||||
|
@ -247,7 +253,7 @@ func (node *TreeNode[T]) each(callback func(*TreeNode[T])) {
|
||||||
|
|
||||||
// Called when the node was fully parsed and needs to decide the next control flow.
|
// Called when the node was fully parsed and needs to decide the next control flow.
|
||||||
// finish is only called from `tree.Add`.
|
// finish is only called from `tree.Add`.
|
||||||
func (node *TreeNode[T]) finish(path string, data T, i int, offset int) (*TreeNode[T], int, Flow) {
|
func (node *Node[T]) finish(path string, data T, i int, offset int) (*Node[T], int, Flow) {
|
||||||
char := path[i]
|
char := path[i]
|
||||||
|
|
||||||
if char >= node.start && char < node.end {
|
if char >= node.start && char < node.end {
|
|
@ -1,6 +0,0 @@
|
||||||
package router
|
|
||||||
|
|
||||||
type Parameter struct {
|
|
||||||
Key string
|
|
||||||
Value string
|
|
||||||
}
|
|
13
router.go
13
router.go
|
@ -1,5 +1,18 @@
|
||||||
package router
|
package router
|
||||||
|
|
||||||
|
type Flow int
|
||||||
|
|
||||||
|
const (
|
||||||
|
flowStop Flow = iota
|
||||||
|
flowBegin
|
||||||
|
flowNext
|
||||||
|
)
|
||||||
|
|
||||||
|
type Parameter struct {
|
||||||
|
Key string
|
||||||
|
Value string
|
||||||
|
}
|
||||||
|
|
||||||
type Router[T any] struct {
|
type Router[T any] struct {
|
||||||
get Tree[T]
|
get Tree[T]
|
||||||
post Tree[T]
|
post Tree[T]
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
GET /
|
GET /
|
||||||
GET /:slug
|
GET /[slug]
|
||||||
GET /tags
|
GET /tags
|
||||||
GET /tag/:tag
|
GET /tag/[tag]
|
334
tests/github.txt
334
tests/github.txt
|
@ -1,203 +1,203 @@
|
||||||
GET /authorizations
|
GET /authorizations
|
||||||
GET /authorizations/:id
|
GET /authorizations/[id]
|
||||||
POST /authorizations
|
POST /authorizations
|
||||||
DELETE /authorizations/:id
|
DELETE /authorizations/[id]
|
||||||
GET /applications/:client_id/tokens/:access_token
|
GET /applications/[client_id]/tokens/[access_token]
|
||||||
DELETE /applications/:client_id/tokens
|
DELETE /applications/[client_id]/tokens
|
||||||
DELETE /applications/:client_id/tokens/:access_token
|
DELETE /applications/[client_id]/tokens/[access_token]
|
||||||
GET /events
|
GET /events
|
||||||
GET /repos/:owner/:repo/events
|
GET /repos/[owner]/[repo]/events
|
||||||
GET /networks/:owner/:repo/events
|
GET /networks/[owner]/[repo]/events
|
||||||
GET /orgs/:org/events
|
GET /orgs/[org]/events
|
||||||
GET /users/:user/received_events
|
GET /users/[user]/received_events
|
||||||
GET /users/:user/received_events/public
|
GET /users/[user]/received_events/public
|
||||||
GET /users/:user/events
|
GET /users/[user]/events
|
||||||
GET /users/:user/events/public
|
GET /users/[user]/events/public
|
||||||
GET /users/:user/events/orgs/:org
|
GET /users/[user]/events/orgs/[org]
|
||||||
GET /feeds
|
GET /feeds
|
||||||
GET /notifications
|
GET /notifications
|
||||||
GET /repos/:owner/:repo/notifications
|
GET /repos/[owner]/[repo]/notifications
|
||||||
PUT /notifications
|
PUT /notifications
|
||||||
PUT /repos/:owner/:repo/notifications
|
PUT /repos/[owner]/[repo]/notifications
|
||||||
GET /notifications/threads/:id
|
GET /notifications/threads/[id]
|
||||||
GET /notifications/threads/:id/subscription
|
GET /notifications/threads/[id]/subscription
|
||||||
PUT /notifications/threads/:id/subscription
|
PUT /notifications/threads/[id]/subscription
|
||||||
DELETE /notifications/threads/:id/subscription
|
DELETE /notifications/threads/[id]/subscription
|
||||||
GET /repos/:owner/:repo/stargazers
|
GET /repos/[owner]/[repo]/stargazers
|
||||||
GET /users/:user/starred
|
GET /users/[user]/starred
|
||||||
GET /user/starred
|
GET /user/starred
|
||||||
GET /user/starred/:owner/:repo
|
GET /user/starred/[owner]/[repo]
|
||||||
PUT /user/starred/:owner/:repo
|
PUT /user/starred/[owner]/[repo]
|
||||||
DELETE /user/starred/:owner/:repo
|
DELETE /user/starred/[owner]/[repo]
|
||||||
GET /repos/:owner/:repo/subscribers
|
GET /repos/[owner]/[repo]/subscribers
|
||||||
GET /users/:user/subscriptions
|
GET /users/[user]/subscriptions
|
||||||
GET /user/subscriptions
|
GET /user/subscriptions
|
||||||
GET /repos/:owner/:repo/subscription
|
GET /repos/[owner]/[repo]/subscription
|
||||||
PUT /repos/:owner/:repo/subscription
|
PUT /repos/[owner]/[repo]/subscription
|
||||||
DELETE /repos/:owner/:repo/subscription
|
DELETE /repos/[owner]/[repo]/subscription
|
||||||
GET /user/subscriptions/:owner/:repo
|
GET /user/subscriptions/[owner]/[repo]
|
||||||
PUT /user/subscriptions/:owner/:repo
|
PUT /user/subscriptions/[owner]/[repo]
|
||||||
DELETE /user/subscriptions/:owner/:repo
|
DELETE /user/subscriptions/[owner]/[repo]
|
||||||
GET /users/:user/gists
|
GET /users/[user]/gists
|
||||||
GET /gists
|
GET /gists
|
||||||
GET /gists/:id
|
GET /gists/[id]
|
||||||
POST /gists
|
POST /gists
|
||||||
PUT /gists/:id/star
|
PUT /gists/[id]/star
|
||||||
DELETE /gists/:id/star
|
DELETE /gists/[id]/star
|
||||||
GET /gists/:id/star
|
GET /gists/[id]/star
|
||||||
POST /gists/:id/forks
|
POST /gists/[id]/forks
|
||||||
DELETE /gists/:id
|
DELETE /gists/[id]
|
||||||
GET /repos/:owner/:repo/git/blobs/:sha
|
GET /repos/[owner]/[repo]/git/blobs/[sha]
|
||||||
POST /repos/:owner/:repo/git/blobs
|
POST /repos/[owner]/[repo]/git/blobs
|
||||||
GET /repos/:owner/:repo/git/commits/:sha
|
GET /repos/[owner]/[repo]/git/commits/[sha]
|
||||||
POST /repos/:owner/:repo/git/commits
|
POST /repos/[owner]/[repo]/git/commits
|
||||||
GET /repos/:owner/:repo/git/refs
|
GET /repos/[owner]/[repo]/git/refs
|
||||||
POST /repos/:owner/:repo/git/refs
|
POST /repos/[owner]/[repo]/git/refs
|
||||||
GET /repos/:owner/:repo/git/tags/:sha
|
GET /repos/[owner]/[repo]/git/tags/[sha]
|
||||||
POST /repos/:owner/:repo/git/tags
|
POST /repos/[owner]/[repo]/git/tags
|
||||||
GET /repos/:owner/:repo/git/trees/:sha
|
GET /repos/[owner]/[repo]/git/trees/[sha]
|
||||||
POST /repos/:owner/:repo/git/trees
|
POST /repos/[owner]/[repo]/git/trees
|
||||||
GET /issues
|
GET /issues
|
||||||
GET /user/issues
|
GET /user/issues
|
||||||
GET /orgs/:org/issues
|
GET /orgs/[org]/issues
|
||||||
GET /repos/:owner/:repo/issues
|
GET /repos/[owner]/[repo]/issues
|
||||||
GET /repos/:owner/:repo/issues/:number
|
GET /repos/[owner]/[repo]/issues/[number]
|
||||||
POST /repos/:owner/:repo/issues
|
POST /repos/[owner]/[repo]/issues
|
||||||
GET /repos/:owner/:repo/assignees
|
GET /repos/[owner]/[repo]/assignees
|
||||||
GET /repos/:owner/:repo/assignees/:assignee
|
GET /repos/[owner]/[repo]/assignees/[assignee]
|
||||||
GET /repos/:owner/:repo/issues/:number/comments
|
GET /repos/[owner]/[repo]/issues/[number]/comments
|
||||||
POST /repos/:owner/:repo/issues/:number/comments
|
POST /repos/[owner]/[repo]/issues/[number]/comments
|
||||||
GET /repos/:owner/:repo/issues/:number/events
|
GET /repos/[owner]/[repo]/issues/[number]/events
|
||||||
GET /repos/:owner/:repo/labels
|
GET /repos/[owner]/[repo]/labels
|
||||||
GET /repos/:owner/:repo/labels/:name
|
GET /repos/[owner]/[repo]/labels/[name]
|
||||||
POST /repos/:owner/:repo/labels
|
POST /repos/[owner]/[repo]/labels
|
||||||
DELETE /repos/:owner/:repo/labels/:name
|
DELETE /repos/[owner]/[repo]/labels/[name]
|
||||||
GET /repos/:owner/:repo/issues/:number/labels
|
GET /repos/[owner]/[repo]/issues/[number]/labels
|
||||||
POST /repos/:owner/:repo/issues/:number/labels
|
POST /repos/[owner]/[repo]/issues/[number]/labels
|
||||||
DELETE /repos/:owner/:repo/issues/:number/labels/:name
|
DELETE /repos/[owner]/[repo]/issues/[number]/labels/[name]
|
||||||
PUT /repos/:owner/:repo/issues/:number/labels
|
PUT /repos/[owner]/[repo]/issues/[number]/labels
|
||||||
DELETE /repos/:owner/:repo/issues/:number/labels
|
DELETE /repos/[owner]/[repo]/issues/[number]/labels
|
||||||
GET /repos/:owner/:repo/milestones/:number/labels
|
GET /repos/[owner]/[repo]/milestones/[number]/labels
|
||||||
GET /repos/:owner/:repo/milestones
|
GET /repos/[owner]/[repo]/milestones
|
||||||
GET /repos/:owner/:repo/milestones/:number
|
GET /repos/[owner]/[repo]/milestones/[number]
|
||||||
POST /repos/:owner/:repo/milestones
|
POST /repos/[owner]/[repo]/milestones
|
||||||
DELETE /repos/:owner/:repo/milestones/:number
|
DELETE /repos/[owner]/[repo]/milestones/[number]
|
||||||
GET /emojis
|
GET /emojis
|
||||||
GET /gitignore/templates
|
GET /gitignore/templates
|
||||||
GET /gitignore/templates/:name
|
GET /gitignore/templates/[name]
|
||||||
POST /markdown
|
POST /markdown
|
||||||
POST /markdown/raw
|
POST /markdown/raw
|
||||||
GET /meta
|
GET /meta
|
||||||
GET /rate_limit
|
GET /rate_limit
|
||||||
GET /users/:user/orgs
|
GET /users/[user]/orgs
|
||||||
GET /user/orgs
|
GET /user/orgs
|
||||||
GET /orgs/:org
|
GET /orgs/[org]
|
||||||
GET /orgs/:org/members
|
GET /orgs/[org]/members
|
||||||
GET /orgs/:org/members/:user
|
GET /orgs/[org]/members/[user]
|
||||||
DELETE /orgs/:org/members/:user
|
DELETE /orgs/[org]/members/[user]
|
||||||
GET /orgs/:org/public_members
|
GET /orgs/[org]/public_members
|
||||||
GET /orgs/:org/public_members/:user
|
GET /orgs/[org]/public_members/[user]
|
||||||
PUT /orgs/:org/public_members/:user
|
PUT /orgs/[org]/public_members/[user]
|
||||||
DELETE /orgs/:org/public_members/:user
|
DELETE /orgs/[org]/public_members/[user]
|
||||||
GET /orgs/:org/teams
|
GET /orgs/[org]/teams
|
||||||
GET /teams/:id
|
GET /teams/[id]
|
||||||
POST /orgs/:org/teams
|
POST /orgs/[org]/teams
|
||||||
DELETE /teams/:id
|
DELETE /teams/[id]
|
||||||
GET /teams/:id/members
|
GET /teams/[id]/members
|
||||||
GET /teams/:id/members/:user
|
GET /teams/[id]/members/[user]
|
||||||
PUT /teams/:id/members/:user
|
PUT /teams/[id]/members/[user]
|
||||||
DELETE /teams/:id/members/:user
|
DELETE /teams/[id]/members/[user]
|
||||||
GET /teams/:id/repos
|
GET /teams/[id]/repos
|
||||||
GET /teams/:id/repos/:owner/:repo
|
GET /teams/[id]/repos/[owner]/[repo]
|
||||||
PUT /teams/:id/repos/:owner/:repo
|
PUT /teams/[id]/repos/[owner]/[repo]
|
||||||
DELETE /teams/:id/repos/:owner/:repo
|
DELETE /teams/[id]/repos/[owner]/[repo]
|
||||||
GET /user/teams
|
GET /user/teams
|
||||||
GET /repos/:owner/:repo/pulls
|
GET /repos/[owner]/[repo]/pulls
|
||||||
GET /repos/:owner/:repo/pulls/:number
|
GET /repos/[owner]/[repo]/pulls/[number]
|
||||||
POST /repos/:owner/:repo/pulls
|
POST /repos/[owner]/[repo]/pulls
|
||||||
GET /repos/:owner/:repo/pulls/:number/commits
|
GET /repos/[owner]/[repo]/pulls/[number]/commits
|
||||||
GET /repos/:owner/:repo/pulls/:number/files
|
GET /repos/[owner]/[repo]/pulls/[number]/files
|
||||||
GET /repos/:owner/:repo/pulls/:number/merge
|
GET /repos/[owner]/[repo]/pulls/[number]/merge
|
||||||
PUT /repos/:owner/:repo/pulls/:number/merge
|
PUT /repos/[owner]/[repo]/pulls/[number]/merge
|
||||||
GET /repos/:owner/:repo/pulls/:number/comments
|
GET /repos/[owner]/[repo]/pulls/[number]/comments
|
||||||
PUT /repos/:owner/:repo/pulls/:number/comments
|
PUT /repos/[owner]/[repo]/pulls/[number]/comments
|
||||||
GET /user/repos
|
GET /user/repos
|
||||||
GET /users/:user/repos
|
GET /users/[user]/repos
|
||||||
GET /orgs/:org/repos
|
GET /orgs/[org]/repos
|
||||||
GET /repositories
|
GET /repositories
|
||||||
POST /user/repos
|
POST /user/repos
|
||||||
POST /orgs/:org/repos
|
POST /orgs/[org]/repos
|
||||||
GET /repos/:owner/:repo
|
GET /repos/[owner]/[repo]
|
||||||
GET /repos/:owner/:repo/contributors
|
GET /repos/[owner]/[repo]/contributors
|
||||||
GET /repos/:owner/:repo/languages
|
GET /repos/[owner]/[repo]/languages
|
||||||
GET /repos/:owner/:repo/teams
|
GET /repos/[owner]/[repo]/teams
|
||||||
GET /repos/:owner/:repo/tags
|
GET /repos/[owner]/[repo]/tags
|
||||||
GET /repos/:owner/:repo/branches
|
GET /repos/[owner]/[repo]/branches
|
||||||
GET /repos/:owner/:repo/branches/:branch
|
GET /repos/[owner]/[repo]/branches/[branch]
|
||||||
DELETE /repos/:owner/:repo
|
DELETE /repos/[owner]/[repo]
|
||||||
GET /repos/:owner/:repo/collaborators
|
GET /repos/[owner]/[repo]/collaborators
|
||||||
GET /repos/:owner/:repo/collaborators/:user
|
GET /repos/[owner]/[repo]/collaborators/[user]
|
||||||
PUT /repos/:owner/:repo/collaborators/:user
|
PUT /repos/[owner]/[repo]/collaborators/[user]
|
||||||
DELETE /repos/:owner/:repo/collaborators/:user
|
DELETE /repos/[owner]/[repo]/collaborators/[user]
|
||||||
GET /repos/:owner/:repo/comments
|
GET /repos/[owner]/[repo]/comments
|
||||||
GET /repos/:owner/:repo/commits/:sha/comments
|
GET /repos/[owner]/[repo]/commits/[sha]/comments
|
||||||
POST /repos/:owner/:repo/commits/:sha/comments
|
POST /repos/[owner]/[repo]/commits/[sha]/comments
|
||||||
GET /repos/:owner/:repo/comments/:id
|
GET /repos/[owner]/[repo]/comments/[id]
|
||||||
DELETE /repos/:owner/:repo/comments/:id
|
DELETE /repos/[owner]/[repo]/comments/[id]
|
||||||
GET /repos/:owner/:repo/commits
|
GET /repos/[owner]/[repo]/commits
|
||||||
GET /repos/:owner/:repo/commits/:sha
|
GET /repos/[owner]/[repo]/commits/[sha]
|
||||||
GET /repos/:owner/:repo/readme
|
GET /repos/[owner]/[repo]/readme
|
||||||
GET /repos/:owner/:repo/keys
|
GET /repos/[owner]/[repo]/keys
|
||||||
GET /repos/:owner/:repo/keys/:id
|
GET /repos/[owner]/[repo]/keys/[id]
|
||||||
POST /repos/:owner/:repo/keys
|
POST /repos/[owner]/[repo]/keys
|
||||||
DELETE /repos/:owner/:repo/keys/:id
|
DELETE /repos/[owner]/[repo]/keys/[id]
|
||||||
GET /repos/:owner/:repo/downloads
|
GET /repos/[owner]/[repo]/downloads
|
||||||
GET /repos/:owner/:repo/downloads/:id
|
GET /repos/[owner]/[repo]/downloads/[id]
|
||||||
DELETE /repos/:owner/:repo/downloads/:id
|
DELETE /repos/[owner]/[repo]/downloads/[id]
|
||||||
GET /repos/:owner/:repo/forks
|
GET /repos/[owner]/[repo]/forks
|
||||||
POST /repos/:owner/:repo/forks
|
POST /repos/[owner]/[repo]/forks
|
||||||
GET /repos/:owner/:repo/hooks
|
GET /repos/[owner]/[repo]/hooks
|
||||||
GET /repos/:owner/:repo/hooks/:id
|
GET /repos/[owner]/[repo]/hooks/[id]
|
||||||
POST /repos/:owner/:repo/hooks
|
POST /repos/[owner]/[repo]/hooks
|
||||||
POST /repos/:owner/:repo/hooks/:id/tests
|
POST /repos/[owner]/[repo]/hooks/[id]/tests
|
||||||
DELETE /repos/:owner/:repo/hooks/:id
|
DELETE /repos/[owner]/[repo]/hooks/[id]
|
||||||
POST /repos/:owner/:repo/merges
|
POST /repos/[owner]/[repo]/merges
|
||||||
GET /repos/:owner/:repo/releases
|
GET /repos/[owner]/[repo]/releases
|
||||||
GET /repos/:owner/:repo/releases/:id
|
GET /repos/[owner]/[repo]/releases/[id]
|
||||||
POST /repos/:owner/:repo/releases
|
POST /repos/[owner]/[repo]/releases
|
||||||
DELETE /repos/:owner/:repo/releases/:id
|
DELETE /repos/[owner]/[repo]/releases/[id]
|
||||||
GET /repos/:owner/:repo/releases/:id/assets
|
GET /repos/[owner]/[repo]/releases/[id]/assets
|
||||||
GET /repos/:owner/:repo/stats/contributors
|
GET /repos/[owner]/[repo]/stats/contributors
|
||||||
GET /repos/:owner/:repo/stats/commit_activity
|
GET /repos/[owner]/[repo]/stats/commit_activity
|
||||||
GET /repos/:owner/:repo/stats/code_frequency
|
GET /repos/[owner]/[repo]/stats/code_frequency
|
||||||
GET /repos/:owner/:repo/stats/participation
|
GET /repos/[owner]/[repo]/stats/participation
|
||||||
GET /repos/:owner/:repo/stats/punch_card
|
GET /repos/[owner]/[repo]/stats/punch_card
|
||||||
GET /repos/:owner/:repo/statuses/:ref
|
GET /repos/[owner]/[repo]/statuses/[ref]
|
||||||
POST /repos/:owner/:repo/statuses/:ref
|
POST /repos/[owner]/[repo]/statuses/[ref]
|
||||||
GET /search/repositories
|
GET /search/repositories
|
||||||
GET /search/code
|
GET /search/code
|
||||||
GET /search/issues
|
GET /search/issues
|
||||||
GET /search/users
|
GET /search/users
|
||||||
GET /legacy/issues/search/:owner/:repository/:state/:keyword
|
GET /legacy/issues/search/[owner]/[repository]/[state]/[keyword]
|
||||||
GET /legacy/repos/search/:keyword
|
GET /legacy/repos/search/[keyword]
|
||||||
GET /legacy/user/search/:keyword
|
GET /legacy/user/search/[keyword]
|
||||||
GET /legacy/user/email/:email
|
GET /legacy/user/email/[email]
|
||||||
GET /users/:user
|
GET /users/[user]
|
||||||
GET /user
|
GET /user
|
||||||
GET /users
|
GET /users
|
||||||
GET /user/emails
|
GET /user/emails
|
||||||
POST /user/emails
|
POST /user/emails
|
||||||
DELETE /user/emails
|
DELETE /user/emails
|
||||||
GET /users/:user/followers
|
GET /users/[user]/followers
|
||||||
GET /user/followers
|
GET /user/followers
|
||||||
GET /users/:user/following
|
GET /users/[user]/following
|
||||||
GET /user/following
|
GET /user/following
|
||||||
GET /user/following/:user
|
GET /user/following/[user]
|
||||||
GET /users/:user/following/:target_user
|
GET /users/[user]/following/[target_user]
|
||||||
PUT /user/following/:user
|
PUT /user/following/[user]
|
||||||
DELETE /user/following/:user
|
DELETE /user/following/[user]
|
||||||
GET /users/:user/keys
|
GET /users/[user]/keys
|
||||||
GET /user/keys
|
GET /user/keys
|
||||||
GET /user/keys/:id
|
GET /user/keys/[id]
|
||||||
POST /user/keys
|
POST /user/keys
|
||||||
DELETE /user/keys/:id
|
DELETE /user/keys/[id]
|
15
tree.go
15
tree.go
|
@ -1,13 +1,12 @@
|
||||||
package router
|
package router
|
||||||
|
|
||||||
// Super-fancy radix tree
|
// Representation of a node tree
|
||||||
type Tree[T any] struct {
|
type Tree[T any] struct {
|
||||||
root TreeNode[T]
|
root Node[T]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adds a new element to the tree
|
// Adds a new path to the tree
|
||||||
func (tree *Tree[T]) Add(path string, data T) {
|
func (tree *Tree[T]) Add(path string, data T) {
|
||||||
// Search tree for equal parts until we can no longer proceed
|
|
||||||
i := 0
|
i := 0
|
||||||
offset := 0
|
offset := 0
|
||||||
node := &tree.root
|
node := &tree.root
|
||||||
|
@ -17,8 +16,8 @@ func (tree *Tree[T]) Add(path string, data T) {
|
||||||
switch node.kind {
|
switch node.kind {
|
||||||
case parameter:
|
case parameter:
|
||||||
// This only occurs when the same parameter based route is added twice.
|
// This only occurs when the same parameter based route is added twice.
|
||||||
// node: /post/:id|
|
// node: /post/[id|
|
||||||
// path: /post/:id|
|
// path: /post/[id|
|
||||||
if i == len(path) {
|
if i == len(path) {
|
||||||
node.data = data
|
node.data = data
|
||||||
return
|
return
|
||||||
|
@ -94,7 +93,7 @@ func (tree *Tree[T]) LookupNoAlloc(path string, addParameter func(key string, va
|
||||||
var (
|
var (
|
||||||
i uint
|
i uint
|
||||||
wildcardPath string
|
wildcardPath string
|
||||||
wildcard *TreeNode[T]
|
wildcard *Node[T]
|
||||||
node = &tree.root
|
node = &tree.root
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -189,7 +188,7 @@ notFound:
|
||||||
|
|
||||||
// Binds all handlers to a new one provided by the callback.
|
// Binds all handlers to a new one provided by the callback.
|
||||||
func (tree *Tree[T]) Map(transform func(T) T) {
|
func (tree *Tree[T]) Map(transform func(T) T) {
|
||||||
tree.root.each(func(node *TreeNode[T]) {
|
tree.root.each(func(node *Node[T]) {
|
||||||
node.data = transform(node.data)
|
node.data = transform(node.data)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user