Skip to content

Commit

Permalink
refactor cbor V1 / V2 codecs, return a V1 encoder in the NewCborCodec()
Browse files Browse the repository at this point in the history
  • Loading branch information
lukseven committed Jan 15, 2025
1 parent be0b92f commit 9b52166
Show file tree
Hide file tree
Showing 10 changed files with 36 additions and 28 deletions.
2 changes: 1 addition & 1 deletion format/codecs/cbor_tags_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import (
"github.com/eluv-io/common-go/util/maputil"
)

var cborCodec = codecs.NewCborCodec()
var cborCodec = codecs.NewCborV2Codec()

func TestIDTag(t *testing.T) {
factory := format.NewFactory()
Expand Down
21 changes: 15 additions & 6 deletions format/codecs/codecs.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,10 @@ var (
JsonMultiCodec = NewMultiCodec(JsonCodec, JsonMultiCodecPath)
CborV1MultiCodec = NewMultiCodec(CborV1Codec, CborV1MultiCodecPath)
CborV2MultiCodec = NewMultiCodec(CborV2Codec, CborV2MultiCodecPath)
// CborMuxCodec is the codec producing versioned V2 format and supports decoding un-versioned V1 format.
CborMuxCodec = NewMuxCodec(CborV2MultiCodec, CborV1MultiCodec.DisableVersions())
// CborV1MuxCodec is the codec producing un-versioned V1 format and supports decoding versioned V2 format.
CborV1MuxCodec = NewMuxCodec(CborV1MultiCodec.DisableVersions(), CborV2MultiCodec)
// CborV2MuxCodec is the codec producing versioned V2 format and supports decoding un-versioned V1 format.
CborV2MuxCodec = NewMuxCodec(CborV2MultiCodec, CborV1MultiCodec.DisableVersions())
)

// NewGobCodec creates a new streaming MultiCodec using the encoding/gob format.
Expand All @@ -47,9 +49,16 @@ func NewJsonCodec() MultiCodec {
return JsonMultiCodec
}

// NewCborCodec creates a new streaming MultiCodec using the CBOR format.
// NewCborCodec returns a MultiCodec using the CBOR format. It encodes/decodes un-versioned V1 format and supports
// decoding versioned V2 format.
func NewCborCodec() MultiCodec {
return CborMuxCodec
return CborV1MuxCodec
}

// NewCborV2Codec returns a MultiCodec using the CBOR format. It encodes/decodes versioned V2 format and supports
// decoding un-versioned V1 format.
func NewCborV2Codec() MultiCodec {
return CborV2MuxCodec
}

// MdsImexCodec returns the codec for metadata store exports / imports.
Expand All @@ -60,13 +69,13 @@ func MdsImexCodec() MultiCodec {
// CborEncode encodes the given value as CBOR and writes it to the writer without MultiCodec support (i.e. no MultiCodec
// header is written).
func CborEncode(w io.Writer, v interface{}) error {
return CborV2Codec.Encoder(w).Encode(v)
return NewCborCodec().Encoder(w).Encode(v)
}

// CborDecode decodes cbor-encoded data from the provided reader into the given data structure. The data is not expected
// to have a MultiCodec header.
func CborDecode(r io.Reader, v interface{}) error {
return CborV2Codec.Decoder(r).Decode(v)
return NewCborCodec().Decoder(r).Decode(v)
}

func makeGobCodec() Codec {
Expand Down
10 changes: 5 additions & 5 deletions format/codecs/codecs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,19 @@ func TestGobCodec(t *testing.T) {
}

func TestCborCodec(t *testing.T) {
runCodecTest(t, NewCborCodec())
runCodecTestInterface(t, NewCborCodec())
runCodecTest(t, NewCborV2Codec())
runCodecTestInterface(t, NewCborV2Codec())
}

// TestCborV1Codec encodes data with CborV1MultiCodec and decodes it with CborMuxCodec.
// TestCborV1Codec encodes data with CborV1MultiCodec and decodes it with CborV2MuxCodec.
func TestCborV1Codec(t *testing.T) {
{
buf, data := encode(t, CborV1MultiCodec)
decode(CborMuxCodec, buf, data, t)
decode(CborV2MuxCodec, buf, data, t)
}
{
buf, data := encode(t, CborV1MultiCodec)
decodeInterface(CborMuxCodec, buf, data, t)
decodeInterface(CborV2MuxCodec, buf, data, t)
}
}

Expand Down
2 changes: 1 addition & 1 deletion format/codecs/multi.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ type MultiCodec interface {
// the version during decoding.
//
// This feature is needed in order to support mux codecs where encoding uses versions, but where legacy data was
// encoded without versions. See CborMuxCodec and TestVersionedMux.
// encoded without versions. See CborV2MuxCodec and TestVersionedMux.
DisableVersions() MultiCodec
}

Expand Down
2 changes: 1 addition & 1 deletion format/codecs/multi_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ func TestMultiCodecs(t *testing.T) {
codecs.JsonMultiCodec,
codecs.CborV1MultiCodec,
codecs.CborV2MultiCodec,
codecs.CborMuxCodec,
codecs.CborV2MuxCodec,
}

tests := []struct {
Expand Down
10 changes: 5 additions & 5 deletions format/codecs/mux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,9 @@ type testStructV2 struct {
// - An initial data structure is encoded with the cbor V1 codec.
// - Then the codec is upgraded to V2 for improved performance and versioning is added for future-proofing.
// - Then the data structure changes and now gets encoded in a new format (as a CBOR array instead of a map).
// - Finally, all three versions of the encoded data are decoded with the same CborMuxCodec.
// - Finally, all three versions of the encoded data are decoded with the same CborV2MuxCodec.
//
// In order to make decoding of the initial encoded data work, the CborMuxCodec disables versions on the legacy
// In order to make decoding of the initial encoded data work, the CborV2MuxCodec disables versions on the legacy
// CborV1MultiCodec, since that data was encoded without version information.
func TestVersionedMux(t *testing.T) {
hsh := hash.MustParse("hq__2w1SR2eY9LChsaY5f3EE2G4RhroKnmL7dsyB7Wm2qvbRG5UF9GoPVgFvD1nFqe9Pt4hF7")
Expand All @@ -90,14 +90,14 @@ func TestVersionedMux(t *testing.T) {
require.NoError(t, codecs.CborV1MultiCodec.Encoder(bufCbor).Encode(dataV1))

bufCborV2DataV1 := new(bytes.Buffer)
require.NoError(t, codecs.CborMuxCodec.VersionedEncoder(bufCborV2DataV1).EncodeVersioned(1, dataV1))
require.NoError(t, codecs.CborV2MuxCodec.VersionedEncoder(bufCborV2DataV1).EncodeVersioned(1, dataV1))

bufCborV2DataV2 := new(bytes.Buffer)
require.NoError(t, codecs.CborMuxCodec.VersionedEncoder(bufCborV2DataV2).EncodeVersioned(2, dataV2))
require.NoError(t, codecs.CborV2MuxCodec.VersionedEncoder(bufCborV2DataV2).EncodeVersioned(2, dataV2))

for i, buf := range []*bytes.Buffer{bufCbor, bufCborV2DataV1, bufCborV2DataV2} {
fmt.Println(buf.String())
obj, version, err := codecs.CborMuxCodec.VersionedDecoder(buf).DecodeVersioned(
obj, version, err := codecs.CborV2MuxCodec.VersionedDecoder(buf).DecodeVersioned(
func(version uint, codec string) interface{} {
if codec == codecs.CborV1MultiCodec.Header().Path() {
return &testStruct{}
Expand Down
4 changes: 2 additions & 2 deletions format/link/blob_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ func TestBlobLinkCborMarshaling(t *testing.T) {
data := []byte("###blob bytes###")
lnk := link.NewBlobBuilder().Data(data).EncryptionScheme(encryption.None).MustBuild()

codec := codecs.NewCborCodec()
codec := codecs.NewCborV2Codec()

{
lnkBuf := &bytes.Buffer{}
Expand Down Expand Up @@ -170,7 +170,7 @@ func xTestDecodeSlice(t *testing.T) {

watch := timeutil.StartWatch()
log.Info("start")
//err = codecutil.MapDecode(data, &target)
// err = codecutil.MapDecode(data, &target)
err = mapstructure.Decode(data, &target)
log.Info("end", "duration", watch.Duration())

Expand Down
6 changes: 3 additions & 3 deletions format/link/link_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,7 @@ func testJSON(t *testing.T, lnk *link.Link, expJson string) {
}

func testCBOR(t *testing.T, lnk *link.Link) {
codec := codecs.NewCborCodec()
codec := codecs.NewCborV2Codec()

buf := &bytes.Buffer{}
err := codec.Encoder(buf).Encode(lnk)
Expand Down Expand Up @@ -498,7 +498,7 @@ func testWrappedCBOR(t *testing.T, tc testCase) {
s := Wrapper{
Link: *tc.lnk,
}
codec := codecs.NewCborCodec()
codec := codecs.NewCborV2Codec()

buf := &bytes.Buffer{}
err := codec.Encoder(buf).Encode(s)
Expand Down Expand Up @@ -528,7 +528,7 @@ func replaceHashes(s string) string {
}

func cbor(t *testing.T, src interface{}) interface{} {
codec := codecs.NewCborCodec()
codec := codecs.NewCborV2Codec()
buf := &bytes.Buffer{}
err := codec.Encoder(buf).Encode(src)
require.NoError(t, err)
Expand Down
4 changes: 2 additions & 2 deletions format/token/token_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,9 @@ func TestNil(t *testing.T) {
require.True(t, tokWrapper.Token.IsNil())

buf := bytes.NewBuffer(nil)
err = codecs.CborMuxCodec.Encoder(buf).Encode(tokWrapper)
err = codecs.CborV2MuxCodec.Encoder(buf).Encode(tokWrapper)
require.NoError(t, err)
err = codecs.CborMuxCodec.Decoder(buf).Decode(&tokWrapper)
err = codecs.CborV2MuxCodec.Decoder(buf).Decode(&tokWrapper)
require.NoError(t, err)
require.True(t, tokWrapper.Token.IsNil())
}
Expand Down
3 changes: 1 addition & 2 deletions format/unmarshal_regression_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (

"github.com/stretchr/testify/require"

"github.com/eluv-io/common-go/format"
"github.com/eluv-io/common-go/format/codecs"
"github.com/eluv-io/common-go/format/encryption"
"github.com/eluv-io/common-go/format/hash"
Expand Down Expand Up @@ -175,7 +174,7 @@ var dataV1 = &DataStructV1{

var (
blobData = []byte("some blob data")
cborCodec = format.NewFactory().NewMetadataCodec()
cborCodec = codecs.NewCborV2Codec()
)

func marshal(t require.TestingT, data interface{}) ([]byte, []byte) {
Expand Down

0 comments on commit 9b52166

Please sign in to comment.