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) }