From 7f0e04a3f2ce3beeb74117193ba1dbedc6c3bdf9 Mon Sep 17 00:00:00 2001 From: Matthieu Vachon Date: Fri, 8 Mar 2019 17:17:44 -0500 Subject: [PATCH] Added support for int compression type in JSON It appears that `eosjs` output the `compression` fied in JSON using an integer. This passes when sent to `nodeos` so it seems it's correctly supported. Source code of `nodeos` also seems to implies that is possible to use a string for the `compression` field (from various comments on `cleos` source code). Investigation was not full in the sense that it's not clear if the underlying source supports both. Since the eos-go implementation was supporting string version, I decided to simply added support for `uint8` support if string fails with an unmarshal type error. --- .gitignore | 3 +++ transaction_test.go | 32 ++++++++++++++++++++++++++++++ types.go | 47 ++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 79 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index f1d97b07..1bc34f3f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,5 @@ .envrc .idea + +# Added temporarly until we actually use go.mod in this lib, so it's possible to easily hack the lib as needed +go.mod \ No newline at end of file diff --git a/transaction_test.go b/transaction_test.go index 0dbcbbeb..ebcd9d3d 100644 --- a/transaction_test.go +++ b/transaction_test.go @@ -3,6 +3,8 @@ package eos import ( "encoding/hex" "encoding/json" + "errors" + "fmt" "testing" "github.com/stretchr/testify/assert" @@ -34,3 +36,33 @@ func TestTransactionID(t *testing.T) { assert.Equal(t, test.expectID, trxID) } } + +func TestTransaction_UnmarshalPacked_Compression(t *testing.T) { + tests := []struct { + name string + in string + expected CompressionType + expectedErr error + }{ + {"string/none", `{"compression": "none"}`, CompressionNone, nil}, + {"string/zlib", `{"compression": "zlib"}`, CompressionZlib, nil}, + {"string/unknown", `{"compression": "random"}`, 0, errors.New("unknown compression type random")}, + + {"int/none", `{"compression": 0}`, CompressionNone, nil}, + {"int/zlib", `{"compression": 1}`, CompressionZlib, nil}, + {"int/unknown", `{"compression": 3}`, 0, errors.New("unknown compression type 3")}, + } + + for i, test := range tests { + t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { + var tx *PackedTransaction + err := json.Unmarshal([]byte(test.in), &tx) + if test.expectedErr == nil { + require.NoError(t, err) + assert.Equal(t, test.expected, tx.Compression) + } else { + assert.Equal(t, test.expectedErr, err) + } + }) + } +} diff --git a/types.go b/types.go index 587742c4..a9303320 100644 --- a/types.go +++ b/types.go @@ -89,19 +89,60 @@ func (c CompressionType) MarshalJSON() ([]byte, error) { } func (c *CompressionType) UnmarshalJSON(data []byte) error { + tryNext, err := c.tryUnmarshalJSONAsString(data) + if err != nil && !tryNext { + return err + } + + if tryNext { + _, err := c.tryUnmarshalJSONAsUint8(data) + if err != nil { + return err + } + } + + return nil +} + +func (c *CompressionType) tryUnmarshalJSONAsString(data []byte) (tryNext bool, err error) { var s string - err := json.Unmarshal(data, &s) + err = json.Unmarshal(data, &s) if err != nil { - return err + _, isTypeError := err.(*json.UnmarshalTypeError) + + // Let's continue with next handler is we hit a type error, might be an integer... + return isTypeError, err } switch s { + case "none": + *c = CompressionNone case "zlib": *c = CompressionZlib default: + return false, fmt.Errorf("unknown compression type %s", s) + } + + return false, nil +} + +func (c *CompressionType) tryUnmarshalJSONAsUint8(data []byte) (tryNext bool, err error) { + var s uint8 + err = json.Unmarshal(data, &s) + if err != nil { + return false, err + } + + switch s { + case 0: *c = CompressionNone + case 1: + *c = CompressionZlib + default: + return false, fmt.Errorf("unknown compression type %d", s) } - return nil + + return false, nil } // CurrencyName