106 lines
1.7 KiB
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)
|
|
}
|