diff --git a/go.sum b/go.sum index 5f181b9e..0d1d3e27 100644 --- a/go.sum +++ b/go.sum @@ -11,8 +11,8 @@ github.com/antchfx/htmlquery v1.1.0 h1:KMS88sLl5KP9GUVU2MQIDcQXNQ0M5MGlkC9WlYgAQ github.com/antchfx/htmlquery v1.1.0/go.mod h1:MS9yksVSQXls00iXkiMqXr0J+umL/AmxXKuP28SUJM8= github.com/antchfx/xpath v1.1.0 h1:mJTvYpiHvxNQRD4Lbfin/FodHVCHh2a5KrOFr4ZxMOI= github.com/antchfx/xpath v1.1.0/go.mod h1:Yee4kTMuNiPYJ7nSNorELQMr1J33uOpXDMByNYhvtNk= -github.com/antlr/antlr4 v0.0.0-20190819145818-b43a4c3a8015 h1:StuiJFxQUsxSCzcby6NFZRdEhPkXD5vxN7TZ4MD6T84= -github.com/antlr/antlr4 v0.0.0-20190819145818-b43a4c3a8015/go.mod h1:T7PbCXFs94rrTttyxjbyT5+/1V8T2TYDejxUfHJjw1Y= +github.com/antlr/antlr4 v0.0.0-20191005235324-c81b4e69b6c3 h1:bmbhqj60LNfApeR0sPmGCUXDm20s/gJ8EyYK9+hMe3k= +github.com/antlr/antlr4 v0.0.0-20191005235324-c81b4e69b6c3/go.mod h1:T7PbCXFs94rrTttyxjbyT5+/1V8T2TYDejxUfHJjw1Y= github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8= diff --git a/pkg/stdlib/io/fs/lib.go b/pkg/stdlib/io/fs/lib.go new file mode 100644 index 00000000..fc01ddb0 --- /dev/null +++ b/pkg/stdlib/io/fs/lib.go @@ -0,0 +1,15 @@ +package fs + +import ( + "github.com/MontFerret/ferret/pkg/runtime/core" +) + +// RegisterLib register `FS` namespace functions. +func RegisterLib(ns core.Namespace) error { + return ns. + Namespace("FS"). + RegisterFunctions( + core.NewFunctionsFromMap(map[string]core.Function{ + "READ": Read, + })) +} diff --git a/pkg/stdlib/io/fs/read.go b/pkg/stdlib/io/fs/read.go new file mode 100644 index 00000000..09e4a61f --- /dev/null +++ b/pkg/stdlib/io/fs/read.go @@ -0,0 +1,37 @@ +package fs + +import ( + "context" + "io/ioutil" + + "github.com/MontFerret/ferret/pkg/runtime/core" + "github.com/MontFerret/ferret/pkg/runtime/values" + "github.com/MontFerret/ferret/pkg/runtime/values/types" +) + +// Read reads from a given file. +// @params path (String) - path to file to read from. +// @returns data (Binary) - the read file in binary format. +func Read(_ context.Context, args ...core.Value) (core.Value, error) { + err := core.ValidateArgs(args, 1, 1) + + if err != nil { + return values.None, core.Error(err, "validate arguments number") + } + + err = core.ValidateType(args[0], types.String) + + if err != nil { + return values.None, core.Error(err, "validate [0] argument") + } + + path := args[0].String() + + data, err := ioutil.ReadFile(path) + + if err != nil { + return values.None, core.Error(err, "read file") + } + + return values.NewBinary(data), nil +} diff --git a/pkg/stdlib/io/fs/read_test.go b/pkg/stdlib/io/fs/read_test.go new file mode 100644 index 00000000..a68122f4 --- /dev/null +++ b/pkg/stdlib/io/fs/read_test.go @@ -0,0 +1,79 @@ +package fs_test + +import ( + "context" + "io/ioutil" + "os" + "testing" + + "github.com/MontFerret/ferret/pkg/runtime/core" + "github.com/MontFerret/ferret/pkg/runtime/values" + "github.com/MontFerret/ferret/pkg/runtime/values/types" + "github.com/MontFerret/ferret/pkg/stdlib/io/fs" + + . "github.com/smartystreets/goconvey/convey" +) + +func TestRead(t *testing.T) { + + Convey("Arguments passed", t, func() { + + Convey("No arguments passed", func() { + out, err := fs.Read(context.Background()) + + So(out, ShouldEqual, values.None) + So(err, ShouldBeError) + }) + + Convey("Passed not a string", func() { + args := []core.Value{values.NewInt(0)} + out, err := fs.Read(context.Background(), args...) + + So(out, ShouldEqual, values.None) + So(err, ShouldBeError) + }) + + Convey("Passed more that one argument", func() { + args := []core.Value{ + values.NewString("filepath"), + values.NewInt(0), + } + out, err := fs.Read(context.Background(), args...) + + So(out, ShouldEqual, values.None) + So(err, ShouldBeError) + }) + }) + + Convey("Read from file", t, func() { + + Convey("File exists", func() { + file, err := ioutil.TempFile("", "readtest") + So(err, ShouldBeNil) + + defer func() { + file.Close() + os.Remove(file.Name()) + }() + + text := "s string" + file.WriteString(text) + + fname := values.NewString(file.Name()) + + out, err := fs.Read(context.Background(), fname) + So(err, ShouldBeNil) + + So(out.Type().ID(), ShouldEqual, types.Binary.ID()) + So(out.String(), ShouldEqual, text) + }) + + Convey("File does not exist", func() { + fname := values.NewString("not_exist.file") + + out, err := fs.Read(context.Background(), fname) + So(out, ShouldEqual, values.None) + So(err, ShouldBeError) + }) + }) +} diff --git a/pkg/stdlib/io/lib.go b/pkg/stdlib/io/lib.go new file mode 100644 index 00000000..3ef122b2 --- /dev/null +++ b/pkg/stdlib/io/lib.go @@ -0,0 +1,18 @@ +package io + +import ( + "github.com/MontFerret/ferret/pkg/runtime/core" + "github.com/MontFerret/ferret/pkg/stdlib/io/fs" +) + +// RegisterLib register `IO` namespace functions. +func RegisterLib(ns core.Namespace) error { + io := ns.Namespace("IO") + + err := fs.RegisterLib(io) + if err != nil { + return core.Error(err, "register `FS`") + } + + return nil +} diff --git a/pkg/stdlib/lib.go b/pkg/stdlib/lib.go index 661acff8..cdb19139 100644 --- a/pkg/stdlib/lib.go +++ b/pkg/stdlib/lib.go @@ -5,6 +5,7 @@ import ( "github.com/MontFerret/ferret/pkg/stdlib/arrays" "github.com/MontFerret/ferret/pkg/stdlib/collections" "github.com/MontFerret/ferret/pkg/stdlib/html" + "github.com/MontFerret/ferret/pkg/stdlib/io" "github.com/MontFerret/ferret/pkg/stdlib/math" "github.com/MontFerret/ferret/pkg/stdlib/objects" "github.com/MontFerret/ferret/pkg/stdlib/strings" @@ -41,5 +42,9 @@ func RegisterLib(ns core.Namespace) error { return err } + if err := io.RegisterLib(ns); err != nil { + return err + } + return utils.RegisterLib(ns) }