xgoprev/sjson/dec.go

106 lines
1.7 KiB
Go

package sjson
import "github.com/d5/tengo/v2"
import "encoding/json"
import "io"
import "errors"
import tjson "github.com/d5/tengo/v2/stdlib/json"
import "os"
type Decoder struct {
tengo.ObjectImpl
dec *json.Decoder
end bool
inputName string
}
func (d *Decoder) TypeName() string {
return "*sjson.Decoder"
}
func (d *Decoder) String() string {
return "sjson.Decoder{...}"
}
func NewDecoder(args ...tengo.Object) (tengo.Object, error) {
var inputName string
if len(args) == 0 {
inputName = StrStdin
} else if len(args) > 1 {
return nil, tengo.ErrWrongNumArguments
}
inputObject := args[0]
inputName, ok := tengo.ToString(inputObject)
if !ok {
return nil, tengo.ErrInvalidArgumentType{
Name: "first",
Expected: "stringer",
Found: inputObject.TypeName(),
}
}
var reader io.Reader
var err error
switch {
case inputName == StrStdin :
reader = os.Stdin
default:
reader, err = os.Open(inputName)
if err != nil {
return nil, err
}
}
ret := &Decoder{}
ret.dec = json.NewDecoder(reader)
return ret, nil
}
func (d *Decoder) IndexGet(
index tengo.Object,
) (tengo.Object, error) {
key, ok := tengo.ToString(index)
if !ok {
return nil, tengo.ErrInvalidIndexValueType
}
switch key {
case "decode" :
return &tengo.UserFunction{
Name: "decode",
Value: d.Decode,
}, nil
}
// Nothing found.
return nil, nil
}
func (d *Decoder) Decode(
args ...tengo.Object,
) (tengo.Object, error) {
if len(args) > 0 {
return nil, tengo.ErrWrongNumArguments
}
if d.end {
return nil, nil
}
var v any
err := d.dec.Decode(&v)
if err != nil {
if errors.Is(err, io.EOF) {
d.end = true
} else {
return nil, err
}
}
bts, err := json.Marshal(v)
if err != nil {
return nil, err
}
return tjson.Decode(bts)
}