基本逻辑完成
This commit is contained in:
134
leaf/context.go
Normal file
134
leaf/context.go
Normal file
@@ -0,0 +1,134 @@
|
||||
package leaf
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/eclipse/paho.golang/paho"
|
||||
"math"
|
||||
)
|
||||
|
||||
// abortIndex represents a typical value used in abort functions.
|
||||
const abortIndex int8 = math.MaxInt8 >> 1
|
||||
|
||||
type endKeyType = string
|
||||
|
||||
const EndKey endKeyType = "end"
|
||||
|
||||
type EndType int
|
||||
|
||||
const (
|
||||
EndTimer EndType = iota + 1
|
||||
EndStop
|
||||
)
|
||||
|
||||
type KeyValue struct {
|
||||
parent *KeyValue
|
||||
key any
|
||||
value any
|
||||
}
|
||||
|
||||
var rootKeyType = &KeyValue{}
|
||||
|
||||
type Context struct {
|
||||
context.Context
|
||||
*paho.Publish
|
||||
engine *Engine
|
||||
|
||||
index int8
|
||||
handlers HandlersChain
|
||||
|
||||
value *KeyValue
|
||||
}
|
||||
|
||||
func WithLeafContext(c context.Context, p *paho.Publish, engine *Engine, handlers HandlersChain) *Context {
|
||||
return &Context{
|
||||
Context: c,
|
||||
Publish: p,
|
||||
engine: engine,
|
||||
index: -1,
|
||||
handlers: handlers,
|
||||
value: rootKeyType,
|
||||
}
|
||||
}
|
||||
|
||||
// HandlerName returns the main handler's name. For example if the handler is "handleGetUsers()",
|
||||
// this function will return "main.handleGetUsers".
|
||||
func (c *Context) HandlerName() string {
|
||||
return nameOfFunction(c.handlers.Last())
|
||||
}
|
||||
|
||||
// HandlerNames returns a list of all registered handlers for this context in descending order,
|
||||
// following the semantics of HandlerName()
|
||||
func (c *Context) HandlerNames() []string {
|
||||
hn := make([]string, 0, len(c.handlers))
|
||||
for _, val := range c.handlers {
|
||||
if val == nil {
|
||||
continue
|
||||
}
|
||||
hn = append(hn, nameOfFunction(val))
|
||||
}
|
||||
return hn
|
||||
}
|
||||
|
||||
// Handler returns the main handler.
|
||||
func (c *Context) Handler() HandlerFunc {
|
||||
return c.handlers.Last()
|
||||
}
|
||||
|
||||
/************************************/
|
||||
/*********** FLOW CONTROL ***********/
|
||||
/************************************/
|
||||
|
||||
// Next should be used only inside middleware.
|
||||
// It executes the pending handlers in the chain inside the calling handler.
|
||||
// See example in GitHub.
|
||||
func (c *Context) Next() {
|
||||
c.index++
|
||||
for c.index < int8(len(c.handlers)) {
|
||||
if c.handlers[c.index] == nil {
|
||||
continue
|
||||
}
|
||||
c.handlers[c.index](c)
|
||||
c.index++
|
||||
}
|
||||
}
|
||||
|
||||
// IsAborted returns true if the current context was aborted.
|
||||
func (c *Context) IsAborted() bool {
|
||||
return c.index >= abortIndex
|
||||
}
|
||||
|
||||
// Abort prevents pending handlers from being called. Note that this will not stop the current handler.
|
||||
// Let's say you have an authorization middleware that validates that the current request is authorized.
|
||||
// If the authorization fails (ex: the password does not match), call Abort to ensure the remaining handlers
|
||||
// for this request are not called.
|
||||
func (c *Context) Abort() {
|
||||
c.index = abortIndex
|
||||
}
|
||||
|
||||
func WithValue[T any](ctx *Context, k any, v T) {
|
||||
ctx.value = &KeyValue{
|
||||
parent: ctx.value,
|
||||
key: k,
|
||||
value: v,
|
||||
}
|
||||
}
|
||||
|
||||
func Value[T any](ctx *Context, k any) (v T) {
|
||||
vo := ctx.value
|
||||
for {
|
||||
if vo.key == k {
|
||||
v, _ = vo.value.(T)
|
||||
break
|
||||
} else if vo.parent == rootKeyType {
|
||||
break
|
||||
}
|
||||
vo = vo.parent
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func WithCancel(ctx *Context) context.CancelFunc {
|
||||
c, cancel := context.WithCancel(ctx.Context)
|
||||
ctx.Context = c
|
||||
return cancel
|
||||
}
|
||||
Reference in New Issue
Block a user