Skip to content

Commit 4b55230

Browse files
committed
feat: add the ability to load a Lua filesystem instead of from OS
This feature extends the Options to load a Lua filesystem instead of loading directly from the OS. This extension uses an interface to allow for user level overrides by requiring Open and Stat functions utilized by LState.
1 parent 2b3f02d commit 4b55230

File tree

5 files changed

+89
-5
lines changed

5 files changed

+89
-5
lines changed

_state.go

+24
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@ type Options struct {
105105
// If `MinimizeStackMemory` is set, the call stack will be automatically grown or shrank up to a limit of
106106
// `CallStackSize` in order to minimize memory usage. This does incur a slight performance penalty.
107107
MinimizeStackMemory bool
108+
// Load lua files from LuaFileSystem instead of OS file-system.
109+
LuaFileSystem LuaFileSystem
108110
}
109111

110112
/* }}} */
@@ -533,6 +535,28 @@ func (rg *registry) IsFull() bool {
533535

534536
/* }}} */
535537

538+
/* luaFileSystem {{{ */
539+
type LuaFileSystem interface {
540+
Open(path string) (io.ReadCloser, error)
541+
Stat(luapath string) (os.FileInfo, error)
542+
}
543+
544+
func (ls *LState) Open(path string) (io.ReadCloser, error) {
545+
if ls.Options.LuaFileSystem != nil {
546+
return ls.Options.LuaFileSystem.Open(path)
547+
}
548+
return os.Open(path)
549+
}
550+
551+
func (ls *LState) Stat(luapath string) (os.FileInfo, error) {
552+
if ls.Options.LuaFileSystem != nil {
553+
return ls.Options.LuaFileSystem.Stat(luapath)
554+
}
555+
return os.Stat(luapath)
556+
}
557+
558+
/* }}} */
559+
536560
/* Global {{{ */
537561

538562
func newGlobal() *Global {

auxlib.go

+8-4
Original file line numberDiff line numberDiff line change
@@ -350,16 +350,20 @@ func (ls *LState) CallMeta(obj LValue, event string) LValue {
350350
/* load and function call operations {{{ */
351351

352352
func (ls *LState) LoadFile(path string) (*LFunction, error) {
353-
var file *os.File
354-
var err error
353+
var file io.Reader
355354
if len(path) == 0 {
356355
file = os.Stdin
357356
} else {
358-
file, err = os.Open(path)
359-
defer file.Close()
357+
readCloser, err := ls.Open(path)
358+
defer func() {
359+
if readCloser != nil {
360+
readCloser.Close()
361+
}
362+
}()
360363
if err != nil {
361364
return nil, newApiErrorE(ApiErrorFile, err)
362365
}
366+
file = readCloser
363367
}
364368

365369
reader := bufio.NewReader(file)

auxlib_test.go

+32
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package lua
22

33
import (
4+
"embed"
5+
"io"
46
"io/ioutil"
57
"os"
68
"testing"
@@ -335,3 +337,33 @@ func TestLoadFileForEmptyFile(t *testing.T) {
335337
_, err = L.LoadFile(tmpFile.Name())
336338
errorIfNotNil(t, err)
337339
}
340+
341+
//go:embed _lua5.1-tests/all.lua
342+
var luaTree embed.FS
343+
344+
type luaFileSystem struct {
345+
fileSystem embed.FS
346+
}
347+
348+
func (lfs *luaFileSystem) Open(path string) (io.ReadCloser, error) {
349+
return lfs.fileSystem.Open(path)
350+
}
351+
352+
func (lfs *luaFileSystem) Stat(path string) (os.FileInfo, error) {
353+
file, err := lfs.fileSystem.Open(path)
354+
if err != nil {
355+
return nil, err
356+
}
357+
return file.Stat()
358+
}
359+
360+
func TestLoadLuaFileSystemFile(t *testing.T) {
361+
L := NewState(Options{LuaFileSystem: &luaFileSystem{fileSystem: luaTree}})
362+
defer L.Close()
363+
364+
_, err := L.LoadFile("_lua5.1-tests/all.lua")
365+
errorIfNotNil(t, err)
366+
367+
_, err = L.LoadFile("invalid.lua")
368+
errorIfNil(t, err)
369+
}

loadlib.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ func loFindFile(L *LState, name, pname string) (string, string) {
3737
messages := []string{}
3838
for _, pattern := range strings.Split(string(path), ";") {
3939
luapath := strings.Replace(pattern, "?", name, -1)
40-
if _, err := os.Stat(luapath); err == nil {
40+
if _, err := L.Stat(luapath); err == nil {
4141
return luapath, ""
4242
} else {
4343
messages = append(messages, err.Error())

state.go

+24
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@ type Options struct {
109109
// If `MinimizeStackMemory` is set, the call stack will be automatically grown or shrank up to a limit of
110110
// `CallStackSize` in order to minimize memory usage. This does incur a slight performance penalty.
111111
MinimizeStackMemory bool
112+
// Load lua files from LuaFileSystem instead of OS file-system.
113+
LuaFileSystem LuaFileSystem
112114
}
113115

114116
/* }}} */
@@ -579,6 +581,28 @@ func (rg *registry) IsFull() bool {
579581

580582
/* }}} */
581583

584+
/* luaFileSystem {{{ */
585+
type LuaFileSystem interface {
586+
Open(path string) (io.ReadCloser, error)
587+
Stat(luapath string) (os.FileInfo, error)
588+
}
589+
590+
func (ls *LState) Open(path string) (io.ReadCloser, error) {
591+
if ls.Options.LuaFileSystem != nil {
592+
return ls.Options.LuaFileSystem.Open(path)
593+
}
594+
return os.Open(path)
595+
}
596+
597+
func (ls *LState) Stat(luapath string) (os.FileInfo, error) {
598+
if ls.Options.LuaFileSystem != nil {
599+
return ls.Options.LuaFileSystem.Stat(luapath)
600+
}
601+
return os.Stat(luapath)
602+
}
603+
604+
/* }}} */
605+
582606
/* Global {{{ */
583607

584608
func newGlobal() *Global {

0 commit comments

Comments
 (0)