2023-04-23 17:57:36 +08:00
|
|
|
package cli
|
|
|
|
|
|
|
|
import (
|
2024-01-18 17:11:44 +08:00
|
|
|
"context"
|
2023-04-23 17:57:36 +08:00
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"math"
|
2024-01-19 10:04:37 +08:00
|
|
|
"sync"
|
2023-04-23 17:57:36 +08:00
|
|
|
)
|
|
|
|
|
|
|
|
type Context struct {
|
2024-01-19 10:04:37 +08:00
|
|
|
Id int64
|
|
|
|
seq uint16
|
|
|
|
ctx context.Context
|
|
|
|
wc io.WriteCloser
|
|
|
|
params map[string]string
|
|
|
|
locker sync.RWMutex
|
|
|
|
variables map[string]any
|
|
|
|
args []string
|
2023-04-23 17:57:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func (ctx *Context) reset(id int64, wc io.WriteCloser) {
|
|
|
|
ctx.Id = id
|
|
|
|
ctx.wc = wc
|
|
|
|
ctx.seq = 0
|
2024-01-18 17:11:44 +08:00
|
|
|
ctx.ctx = context.Background()
|
2023-04-23 17:57:36 +08:00
|
|
|
ctx.args = make([]string, 0)
|
|
|
|
ctx.params = make(map[string]string)
|
2024-01-19 10:04:37 +08:00
|
|
|
ctx.variables = make(map[string]any)
|
2023-04-23 17:57:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func (ctx *Context) setArgs(args []string) {
|
|
|
|
ctx.args = args
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ctx *Context) setParam(ps map[string]string) {
|
|
|
|
ctx.params = ps
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ctx *Context) Bind(v any) (err error) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2024-01-18 17:11:44 +08:00
|
|
|
func (ctx *Context) setContext(c context.Context) {
|
|
|
|
ctx.ctx = c
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ctx *Context) Context() context.Context {
|
2024-01-19 10:04:37 +08:00
|
|
|
return ctx.ctx
|
2024-01-18 17:11:44 +08:00
|
|
|
}
|
|
|
|
|
2023-04-23 17:57:36 +08:00
|
|
|
func (ctx *Context) Argument(index int) string {
|
|
|
|
if index >= len(ctx.args) || index < 0 {
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
return ctx.args[index]
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ctx *Context) Param(s string) string {
|
|
|
|
if v, ok := ctx.params[s]; ok {
|
|
|
|
return v
|
|
|
|
}
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
|
2024-01-19 10:04:37 +08:00
|
|
|
func (ctx *Context) SetValue(name string, value any) {
|
|
|
|
ctx.locker.Lock()
|
|
|
|
if ctx.variables == nil {
|
|
|
|
ctx.variables = make(map[string]any)
|
|
|
|
}
|
|
|
|
ctx.variables[name] = value
|
|
|
|
ctx.locker.Unlock()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ctx *Context) GetValue(name string) (val any, ok bool) {
|
|
|
|
ctx.locker.RLock()
|
|
|
|
defer ctx.locker.RUnlock()
|
|
|
|
val, ok = ctx.variables[name]
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2023-04-23 17:57:36 +08:00
|
|
|
func (ctx *Context) Success(v any) (err error) {
|
|
|
|
return ctx.send(responsePayload{Type: PacketTypeCommand, Data: v})
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ctx *Context) Error(code int, reason string) (err error) {
|
|
|
|
return ctx.send(responsePayload{Type: PacketTypeCommand, Code: code, Reason: reason})
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ctx *Context) Close() (err error) {
|
|
|
|
return ctx.wc.Close()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ctx *Context) send(res responsePayload) (err error) {
|
|
|
|
var (
|
|
|
|
ok bool
|
|
|
|
buf []byte
|
|
|
|
marshal encoder
|
|
|
|
)
|
|
|
|
if res.Code > 0 {
|
|
|
|
err = writeFrame(ctx.wc, &Frame{
|
|
|
|
Feature: Feature,
|
|
|
|
Type: res.Type,
|
|
|
|
Seq: ctx.seq,
|
|
|
|
Flag: FlagComplete,
|
|
|
|
Error: fmt.Sprintf("ERROR(%d): %s", res.Code, res.Reason),
|
|
|
|
})
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if res.Data == nil {
|
|
|
|
buf = OK
|
|
|
|
goto __END
|
|
|
|
}
|
|
|
|
if marshal, ok = res.Data.(encoder); ok {
|
|
|
|
buf, err = marshal.Marshal()
|
|
|
|
goto __END
|
|
|
|
}
|
|
|
|
buf, err = serialize(res.Data)
|
|
|
|
__END:
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
offset := 0
|
|
|
|
chunkSize := math.MaxInt16 - 1
|
|
|
|
n := len(buf) / chunkSize
|
|
|
|
for i := 0; i < n; i++ {
|
2024-01-18 17:11:44 +08:00
|
|
|
if err = writeFrame(ctx.wc, newFrame(res.Type, FlagPortion, ctx.seq, 0, buf[offset:chunkSize+offset])); err != nil {
|
2023-04-23 17:57:36 +08:00
|
|
|
return
|
|
|
|
}
|
|
|
|
offset += chunkSize
|
|
|
|
}
|
2024-01-18 17:11:44 +08:00
|
|
|
err = writeFrame(ctx.wc, newFrame(res.Type, FlagComplete, ctx.seq, 0, buf[offset:]))
|
2023-04-23 17:57:36 +08:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func newContext(id int64, wc io.WriteCloser) *Context {
|
|
|
|
return &Context{
|
|
|
|
Id: id,
|
|
|
|
wc: wc,
|
|
|
|
}
|
|
|
|
}
|