storj/pkg/luacfg/cfg.go
JT Olio 362f447d9f
cmd/statreceiver: lua-scriptable stat receiver (#636)
* cmd/statreceiver: lua-scriptable stat receiver

Change-Id: I3ce0fe3f1ef4b1f4f27eed90bac0e91cfecf22d7

* some updates

Change-Id: I7c3485adcda1278fce01ae077b4761b3ddb9fb7a

* more comments

Change-Id: I0bb22993cd934c3d40fc1da80d07e49e686b80dd

* linter fixes

Change-Id: Ied014304ecb9aadcf00a6b66ad28f856a428d150

* catch errors

Change-Id: I6e1920f1fd941e66199b30bc427285c19769fc70

* review feedback

Change-Id: I9d4051851eab18970c5f5ddcf4ff265508e541d3

* errorgroup improvements

Change-Id: I4699dda3022f0485fbb50c9dafe692d3921734ff

* too tricky

the previous thing was better for memory with lots of errors at a time
but https://play.golang.org/p/RweTMRjoSCt is too much of a foot gun

Change-Id: I23f0b3d77dd4288fcc20b3756a7110359576bf44
2018-12-11 11:24:31 -07:00

86 lines
1.9 KiB
Go

// Copyright (C) 2018 Storj Labs, Inc.
// See LICENSE for copying information.
package luacfg
import (
"fmt"
"io"
"io/ioutil"
"sync"
lua "github.com/Shopify/go-lua"
luar "github.com/jtolds/go-luar"
)
// Scope represents a collection of values registered in a Lua namespace.
type Scope struct {
mtx sync.Mutex
registrations map[string]func(*lua.State) error
}
// NewScope creates an empty Scope.
func NewScope() *Scope {
return &Scope{
registrations: map[string]func(*lua.State) error{},
}
}
// RegisterType allows you to add a Lua function that creates new
// values of the given type to the scope.
func (s *Scope) RegisterType(name string, example interface{}) error {
return s.register(name, example, luar.PushType)
}
// RegisterVal adds the Go value 'value', including Go functions, to the Lua
// scope.
func (s *Scope) RegisterVal(name string, value interface{}) error {
return s.register(name, value, luar.PushValue)
}
func (s *Scope) register(name string, val interface{},
pusher func(l *lua.State, val interface{}) error) error {
s.mtx.Lock()
defer s.mtx.Unlock()
if _, exists := s.registrations[name]; exists {
return fmt.Errorf("Registration %#v already exists", name)
}
s.registrations[name] = func(l *lua.State) error {
err := pusher(l, val)
if err != nil {
return err
}
l.SetGlobal(name)
return nil
}
return nil
}
// Run runs the Lua source represented by in
func (s *Scope) Run(in io.Reader) error {
l := lua.NewState()
luar.SetOptions(l, luar.Options{AllowUnexportedAccess: true})
s.mtx.Lock()
registrations := make([]func(l *lua.State) error, 0, len(s.registrations))
for _, reg := range s.registrations {
registrations = append(registrations, reg)
}
s.mtx.Unlock()
for _, reg := range registrations {
err := reg(l)
if err != nil {
return err
}
}
data, err := ioutil.ReadAll(in)
if err != nil {
return err
}
err = lua.DoString(l, string(data))
return err
}