Skip to content

Commit

Permalink
Merge pull request #45 from polydawn/44-plus
Browse files Browse the repository at this point in the history
option to decode CBOR's undefined to null
  • Loading branch information
warpfork authored Nov 20, 2018
2 parents 2700834 + bbf0067 commit 8b1e46d
Show file tree
Hide file tree
Showing 6 changed files with 33 additions and 23 deletions.
12 changes: 10 additions & 2 deletions cbor/cborDecoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,17 @@ import (
)

type Decoder struct {
r shared.SlickReader
cfg DecodeOptions
r shared.SlickReader

stack []decoderStep // When empty, and step returns done, all done.
step decoderStep // Shortcut to end of stack.
left []int // Statekeeping space for definite-len map and array.
}

func NewDecoder(r io.Reader) (d *Decoder) {
func NewDecoder(cfg DecodeOptions, r io.Reader) (d *Decoder) {
d = &Decoder{
cfg: cfg,
r: shared.NewReader(r),
stack: make([]decoderStep, 0, 10),
left: make([]int, 0, 10),
Expand Down Expand Up @@ -181,6 +183,12 @@ func (d *Decoder) stepHelper_acceptValue(majorByte byte, tokenSlot *Token) (done
case cborSigilNil:
tokenSlot.Type = TNull
return true, nil
case cborSigilUndefined:
if d.cfg.CoerceUndefToNull {
tokenSlot.Type = TNull
return true, nil
}
return true, fmt.Errorf("encountered cbor 'undefined' byte (%x) during decoding", cborSigilUndefined)
case cborSigilFalse:
tokenSlot.Type = TBool
tokenSlot.Bool = false
Expand Down
2 changes: 1 addition & 1 deletion cbor/cborFixtures_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func checkEncoding(t *testing.T, sequence fixtures.Sequence, expectSerial []byte
func checkDecoding(t *testing.T, expectSequence fixtures.Sequence, serial []byte, expectErr error) {
t.Helper()
inputBuf := bytes.NewBuffer(serial)
tokenSrc := NewDecoder(inputBuf)
tokenSrc := NewDecoder(DecodeOptions{}, inputBuf)

// Run steps, advancing until the decoder reports it's done.
// If the decoder keeps yielding more tokens than we expect, that's fine...
Expand Down
16 changes: 8 additions & 8 deletions cbor/cborHelpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,12 @@ func NewMarshallerAtlased(wr io.Writer, atl atlas.Atlas) *Marshaller {
return x
}

func Unmarshal(data []byte, v interface{}) error {
return NewUnmarshaller(bytes.NewBuffer(data)).Unmarshal(v)
func Unmarshal(cfg DecodeOptions, data []byte, v interface{}) error {
return NewUnmarshaller(cfg, bytes.NewBuffer(data)).Unmarshal(v)
}

func UnmarshalAtlased(data []byte, v interface{}, atl atlas.Atlas) error {
return NewUnmarshallerAtlased(bytes.NewBuffer(data), atl).Unmarshal(v)
func UnmarshalAtlased(cfg DecodeOptions, data []byte, v interface{}, atl atlas.Atlas) error {
return NewUnmarshallerAtlased(cfg, bytes.NewBuffer(data), atl).Unmarshal(v)
}

type Unmarshaller struct {
Expand All @@ -90,13 +90,13 @@ func (x *Unmarshaller) Unmarshal(v interface{}) error {
return x.pump.Run()
}

func NewUnmarshaller(r io.Reader) *Unmarshaller {
return NewUnmarshallerAtlased(r, atlas.MustBuild())
func NewUnmarshaller(cfg DecodeOptions, r io.Reader) *Unmarshaller {
return NewUnmarshallerAtlased(cfg, r, atlas.MustBuild())
}
func NewUnmarshallerAtlased(r io.Reader, atl atlas.Atlas) *Unmarshaller {
func NewUnmarshallerAtlased(cfg DecodeOptions, r io.Reader, atl atlas.Atlas) *Unmarshaller {
x := &Unmarshaller{
unmarshaller: obj.NewUnmarshaller(atl),
decoder: NewDecoder(r),
decoder: NewDecoder(cfg, r),
}
x.pump = shared.TokenPump{
x.decoder,
Expand Down
2 changes: 2 additions & 0 deletions cbor/cborOptions.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ type EncodeOptions struct {
func (EncodeOptions) IsEncodeOptions() {}

type DecodeOptions struct {
CoerceUndefToNull bool

// future: options to validate canonical serial order
}

Expand Down
8 changes: 4 additions & 4 deletions cmd/refmt/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func Main(args []string, stdin io.Reader, stdout, stderr io.Writer) int {
Usage: "read cbor, then pretty print it",
Action: func(c *cli.Context) error {
return shared.TokenPump{
cbor.NewDecoder(stdin),
cbor.NewDecoder(cbor.DecodeOptions{}, stdin),
pretty.NewEncoder(stdout),
}.Run()
},
Expand All @@ -55,7 +55,7 @@ func Main(args []string, stdin io.Reader, stdout, stderr io.Writer) int {
Usage: "read cbor in hex, then pretty print it",
Action: func(c *cli.Context) error {
return shared.TokenPump{
cbor.NewDecoder(hexReader(stdin)),
cbor.NewDecoder(cbor.DecodeOptions{}, hexReader(stdin)),
pretty.NewEncoder(stdout),
}.Run()
},
Expand Down Expand Up @@ -102,7 +102,7 @@ func Main(args []string, stdin io.Reader, stdout, stderr io.Writer) int {
Usage: "read cbor, emit equivalent json",
Action: func(c *cli.Context) error {
return shared.TokenPump{
cbor.NewDecoder(stdin),
cbor.NewDecoder(cbor.DecodeOptions{}, stdin),
json.NewEncoder(stdout, json.EncodeOptions{}),
}.Run()
},
Expand All @@ -113,7 +113,7 @@ func Main(args []string, stdin io.Reader, stdout, stderr io.Writer) int {
Usage: "read cbor in hex, emit equivalent json",
Action: func(c *cli.Context) error {
return shared.TokenPump{
cbor.NewDecoder(hexReader(stdin)),
cbor.NewDecoder(cbor.DecodeOptions{}, hexReader(stdin)),
json.NewEncoder(stdout, json.EncodeOptions{}),
}.Run()
},
Expand Down
16 changes: 8 additions & 8 deletions unmarshalHelpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,22 @@ type DecodeOptions interface {
}

func Unmarshal(opts DecodeOptions, data []byte, v interface{}) error {
switch opts.(type) {
switch o2 := opts.(type) {
case json.DecodeOptions:
return json.Unmarshal(data, v)
case cbor.DecodeOptions:
return cbor.Unmarshal(data, v)
return cbor.Unmarshal(o2, data, v)
default:
panic("incorrect usage: unknown DecodeOptions type")
}
}

func UnmarshalAtlased(opts DecodeOptions, data []byte, v interface{}, atl atlas.Atlas) error {
switch opts.(type) {
switch o2 := opts.(type) {
case json.DecodeOptions:
return json.UnmarshalAtlased(data, v, atl)
case cbor.DecodeOptions:
return cbor.UnmarshalAtlased(data, v, atl)
return cbor.UnmarshalAtlased(o2, data, v, atl)
default:
panic("incorrect usage: unknown DecodeOptions type")
}
Expand All @@ -39,22 +39,22 @@ type Unmarshaller interface {
}

func NewUnmarshaller(opts DecodeOptions, r io.Reader) Unmarshaller {
switch opts.(type) {
switch o2 := opts.(type) {
case json.DecodeOptions:
return json.NewUnmarshaller(r)
case cbor.DecodeOptions:
return cbor.NewUnmarshaller(r)
return cbor.NewUnmarshaller(o2, r)
default:
panic("incorrect usage: unknown DecodeOptions type")
}
}

func NewUnmarshallerAtlased(opts DecodeOptions, r io.Reader, atl atlas.Atlas) Unmarshaller {
switch opts.(type) {
switch o2 := opts.(type) {
case json.DecodeOptions:
return json.NewUnmarshallerAtlased(r, atl)
case cbor.DecodeOptions:
return cbor.NewUnmarshallerAtlased(r, atl)
return cbor.NewUnmarshallerAtlased(o2, r, atl)
default:
panic("incorrect usage: unknown DecodeOptions type")
}
Expand Down

0 comments on commit 8b1e46d

Please sign in to comment.