2023-04-01 11:58:02 +02:00
|
|
|
package engine
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2023-04-01 15:47:03 +02:00
|
|
|
"fmt"
|
2023-04-01 11:58:02 +02:00
|
|
|
"io"
|
|
|
|
"log"
|
|
|
|
|
|
|
|
"git.defalsify.org/festive/resource"
|
|
|
|
"git.defalsify.org/festive/state"
|
|
|
|
"git.defalsify.org/festive/vm"
|
|
|
|
)
|
|
|
|
//
|
|
|
|
//type Config struct {
|
|
|
|
// FlagCount uint32
|
|
|
|
// CacheSize uint32
|
|
|
|
//}
|
|
|
|
|
|
|
|
type Engine struct {
|
2023-04-01 15:47:03 +02:00
|
|
|
st *state.State
|
2023-04-01 11:58:02 +02:00
|
|
|
rs resource.Resource
|
|
|
|
}
|
|
|
|
|
2023-04-01 15:47:03 +02:00
|
|
|
func NewEngine(st *state.State, rs resource.Resource) Engine {
|
2023-04-01 11:58:02 +02:00
|
|
|
engine := Engine{st, rs}
|
|
|
|
return engine
|
|
|
|
}
|
|
|
|
|
|
|
|
func(en *Engine) Init(ctx context.Context) error {
|
|
|
|
b := vm.NewLine([]byte{}, vm.MOVE, []string{"root"}, nil, nil)
|
|
|
|
var err error
|
2023-04-01 15:47:03 +02:00
|
|
|
_, err = vm.Run(b, en.st, en.rs, ctx)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
location := en.st.Where()
|
|
|
|
code, err := en.rs.GetCode(location)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return en.st.AppendCode(code)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (en *Engine) Exec(input []byte, ctx context.Context) error {
|
|
|
|
l := uint8(len(input))
|
|
|
|
if l > 255 {
|
|
|
|
return fmt.Errorf("input too long (%v)", l)
|
|
|
|
}
|
|
|
|
input = append([]byte{l}, input...)
|
|
|
|
code, err := en.st.GetCode()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if len(code) == 0 {
|
|
|
|
return fmt.Errorf("no code to execute")
|
|
|
|
}
|
|
|
|
code, err = vm.Apply(input, code, en.st, en.rs, ctx)
|
|
|
|
en.st.SetCode(code)
|
2023-04-01 11:58:02 +02:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
func(en *Engine) WriteResult(w io.Writer) error {
|
|
|
|
location := en.st.Where()
|
|
|
|
v, err := en.st.Get()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
r, err := en.rs.RenderTemplate(location, v)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
c, err := io.WriteString(w, r)
|
|
|
|
log.Printf("%v bytes written as result for %v", c, location)
|
|
|
|
return err
|
|
|
|
}
|