ugorji / go

idiomatic codec and rpc lib for msgpack, cbor, json, etc. msgpack.org[Go]
MIT License
1.85k stars 295 forks source link

inconsistent behavior when decoding a stream #334

Closed primalmotion closed 4 years ago

primalmotion commented 4 years ago

When decoding a stream using the JSON handle, the decoder returns an error related to syntax instead of io.EOF. This is inconsistent with the behavior of the MSGPACK handle as well as with the standard standard JSON library

Using latest release v1.1.7, but this also happens on master.

Here is a reproduction that outputs:

EOF
EOF
json decode error [pos 24]: only encoded map or array can be decoded into a struct
package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "reflect"

    "github.com/ugorji/go/codec"
)

type thing struct {
    Name string `json:"name" msgpack:"name"`
}

func main() {
    withStdLib()
    withCodecMSGPACK()
    withJSONCodecJSON()
}

func withJSONCodecJSON() {

    h := &codec.JsonHandle{}
    h.Canonical = true
    h.MapType = reflect.ValueOf(map[string]interface{}{}).Type()

    data := bytes.NewBuffer(nil)
    enc := codec.NewEncoder(data, h)
    enc.Encode(thing{Name: "a"})
    enc.Encode(thing{Name: "b"})

    dec := codec.NewDecoder(data, h)
    dest := &thing{}

    if err := dec.Decode(dest); err != nil {
        panic(err)
    }
    if err := dec.Decode(dest); err != nil {
        panic(err)
    }
    if err := dec.Decode(dest); err != nil {
        fmt.Println(err) // should show io.EOF
    }
}

func withCodecMSGPACK() {

    h := &codec.MsgpackHandle{}
    h.Canonical = true
    h.WriteExt = true
    h.MapType = reflect.ValueOf(map[string]interface{}{}).Type()
    h.TypeInfos = codec.NewTypeInfos([]string{"msgpack"})

    data := bytes.NewBuffer(nil)
    enc := codec.NewEncoder(data, h)
    enc.Encode(thing{Name: "a"})
    enc.Encode(thing{Name: "b"})

    dec := codec.NewDecoder(data, h)

    dest := &thing{}

    if err := dec.Decode(dest); err != nil {
        panic(err)
    }
    if err := dec.Decode(dest); err != nil {
        panic(err)
    }

    if err := dec.Decode(dest); err != nil {
        fmt.Println(err) // should show io.EOF
    }
}

func withStdLib() {

    data := bytes.NewBuffer(nil)
    enc := json.NewEncoder(data)
    enc.Encode(thing{Name: "a"})
    enc.Encode(thing{Name: "b"})

    dec := json.NewDecoder(data)
    dest := &thing{}

    if err := dec.Decode(dest); err != nil {
        panic(err)
    }
    if err := dec.Decode(dest); err != nil {
        panic(err)
    }

    if err := dec.Decode(dest); err != nil {
        fmt.Println(err) // should show io.EOF
    }
}