working on ijson and wsh magic (#53)

This commit is contained in:
Mike Sawka
2024-06-13 23:54:04 -07:00
committed by GitHub
parent ac53c1bb87
commit 8e3540f754
27 changed files with 996 additions and 223 deletions
+101 -30
View File
@@ -3,64 +3,135 @@
package wshutil
import "reflect"
import (
"encoding/json"
"fmt"
"reflect"
"github.com/wavetermdev/thenextwave/pkg/ijson"
"github.com/wavetermdev/thenextwave/pkg/shellexec"
"github.com/wavetermdev/thenextwave/pkg/tsgen/tsgenmeta"
)
const CommandKey = "command"
const (
CommandSetView = "setview"
CommandSetMeta = "setmeta"
CommandBlockFileAppend = "blockfile:append"
CommandStreamFile = "streamfile"
BlockCommand_Message = "message"
BlockCommand_SetView = "setview"
BlockCommand_SetMeta = "setmeta"
BlockCommand_Input = "controller:input"
BlockCommand_AppendBlockFile = "blockfile:append"
BlockCommand_AppendIJson = "blockfile:appendijson"
)
var CommandToTypeMap = map[string]reflect.Type{
CommandSetView: reflect.TypeOf(SetViewCommand{}),
CommandSetMeta: reflect.TypeOf(SetMetaCommand{}),
BlockCommand_Input: reflect.TypeOf(BlockInputCommand{}),
BlockCommand_SetView: reflect.TypeOf(BlockSetViewCommand{}),
BlockCommand_SetMeta: reflect.TypeOf(BlockSetMetaCommand{}),
BlockCommand_Message: reflect.TypeOf(BlockMessageCommand{}),
BlockCommand_AppendBlockFile: reflect.TypeOf(BlockAppendFileCommand{}),
BlockCommand_AppendIJson: reflect.TypeOf(BlockAppendIJsonCommand{}),
}
type Command interface {
func CommandTypeUnionMeta() tsgenmeta.TypeUnionMeta {
var rtypes []reflect.Type
for _, rtype := range CommandToTypeMap {
rtypes = append(rtypes, rtype)
}
return tsgenmeta.TypeUnionMeta{
BaseType: reflect.TypeOf((*BlockCommand)(nil)).Elem(),
TypeFieldName: "command",
Types: rtypes,
}
}
type baseCommand struct {
Command string `json:"command"`
}
type BlockCommand interface {
GetCommand() string
}
// for unmarshalling
type baseCommand struct {
Command string `json:"command"`
RpcID string `json:"rpcid"`
RpcType string `json:"rpctype"`
type BlockCommandWrapper struct {
BlockCommand
}
type SetViewCommand struct {
Command string `json:"command"`
func ParseCmdMap(cmdMap map[string]any) (BlockCommand, error) {
cmdType, ok := cmdMap[CommandKey].(string)
if !ok {
return nil, fmt.Errorf("no %s field in command map", CommandKey)
}
mapJson, err := json.Marshal(cmdMap)
if err != nil {
return nil, fmt.Errorf("error marshalling command map: %w", err)
}
rtype := CommandToTypeMap[cmdType]
if rtype == nil {
return nil, fmt.Errorf("unknown command type %q", cmdType)
}
cmd := reflect.New(rtype).Interface()
err = json.Unmarshal(mapJson, cmd)
if err != nil {
return nil, fmt.Errorf("error unmarshalling command: %w", err)
}
return cmd.(BlockCommand), nil
}
type BlockInputCommand struct {
Command string `json:"command" tstype:"\"controller:input\""`
InputData64 string `json:"inputdata64,omitempty"`
SigName string `json:"signame,omitempty"`
TermSize *shellexec.TermSize `json:"termsize,omitempty"`
}
func (ic *BlockInputCommand) GetCommand() string {
return BlockCommand_Input
}
type BlockSetViewCommand struct {
Command string `json:"command" tstype:"\"setview\""`
View string `json:"view"`
}
func (svc *SetViewCommand) GetCommand() string {
return CommandSetView
func (svc *BlockSetViewCommand) GetCommand() string {
return BlockCommand_SetView
}
type SetMetaCommand struct {
Command string `json:"command"`
type BlockSetMetaCommand struct {
Command string `json:"command" tstype:"\"setmeta\""`
Meta map[string]any `json:"meta"`
}
func (smc *SetMetaCommand) GetCommand() string {
return CommandSetMeta
func (smc *BlockSetMetaCommand) GetCommand() string {
return BlockCommand_SetMeta
}
type BlockFileAppendCommand struct {
Command string `json:"command"`
type BlockMessageCommand struct {
Command string `json:"command" tstype:"\"message\""`
Message string `json:"message"`
}
func (bmc *BlockMessageCommand) GetCommand() string {
return BlockCommand_Message
}
type BlockAppendFileCommand struct {
Command string `json:"command" tstype:"\"blockfile:append\""`
FileName string `json:"filename"`
Data []byte `json:"data"`
}
func (bfac *BlockFileAppendCommand) GetCommand() string {
return CommandBlockFileAppend
func (bwc *BlockAppendFileCommand) GetCommand() string {
return BlockCommand_AppendBlockFile
}
type StreamFileCommand struct {
Command string `json:"command"`
FileName string `json:"filename"`
type BlockAppendIJsonCommand struct {
Command string `json:"command" tstype:"\"blockfile:appendijson\""`
FileName string `json:"filename"`
Data ijson.Command `json:"data"`
}
func (c *StreamFileCommand) GetCommand() string {
return CommandStreamFile
func (bwc *BlockAppendIJsonCommand) GetCommand() string {
return BlockCommand_AppendIJson
}
+4 -4
View File
@@ -25,7 +25,7 @@ var WaveOSCPrefixBytes = []byte(WaveOSCPrefix)
// JSON = must escape all ASCII control characters ([\x00-\x1F\x7F])
// we can tell the difference between JSON and base64-JSON by the first character: '{' or not
func EncodeWaveOSCMessage(cmd Command) ([]byte, error) {
func EncodeWaveOSCMessage(cmd BlockCommand) ([]byte, error) {
if cmd.GetCommand() == "" {
return nil, fmt.Errorf("Command field not set in struct")
}
@@ -74,7 +74,7 @@ func EncodeWaveOSCMessage(cmd Command) ([]byte, error) {
return buf.Bytes(), nil
}
func decodeWaveOSCMessage(data []byte) (Command, error) {
func decodeWaveOSCMessage(data []byte) (BlockCommand, error) {
var baseCmd baseCommand
err := json.Unmarshal(data, &baseCmd)
if err != nil {
@@ -85,12 +85,12 @@ func decodeWaveOSCMessage(data []byte) (Command, error) {
if err != nil {
return nil, fmt.Errorf("error unmarshalling json: %w", err)
}
return rtnCmd.(Command), nil
return rtnCmd.(BlockCommand), nil
}
// data does not contain the escape sequence, just the innards
// this function implements the switch between JSON and base64-JSON
func DecodeWaveOSCMessage(data []byte) (Command, error) {
func DecodeWaveOSCMessage(data []byte) (BlockCommand, error) {
if len(data) == 0 {
return nil, fmt.Errorf("empty data")
}