Skip to content

Commit

Permalink
Merge pull request #361 from blinklabs-io/feat/cbor-value-tags
Browse files Browse the repository at this point in the history
feat: support for CBOR tags for arbitrarily large ints
  • Loading branch information
agaffney authored Jul 13, 2023
2 parents 64cc17f + 2d70a30 commit 4e6a58d
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 1 deletion.
19 changes: 18 additions & 1 deletion cbor/value.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"encoding/hex"
"encoding/json"
"fmt"
"math/big"
"sort"
"strings"
)
Expand Down Expand Up @@ -94,7 +95,17 @@ func (v *Value) UnmarshalCBOR(data []byte) error {
value: &newValue,
}
} else {
return fmt.Errorf("unsupported CBOR tag: %d", tmpTag.Number)
// Fall back to standard CBOR tag parsing for our supported types
var tmpTagDecode interface{}
if _, err := Decode(data, &tmpTagDecode); err != nil {
return err
}
switch tmpTagDecode.(type) {
case int, uint, int64, uint64, bool, big.Int:
v.value = tmpTagDecode
default:
return fmt.Errorf("unsupported CBOR tag number: %d", tmpTag.Number)
}
}
}
default:
Expand Down Expand Up @@ -218,6 +229,12 @@ func generateAstJson(obj interface{}) ([]byte, error) {
return []byte(tmpJson), nil
case Constructor:
return json.Marshal(obj)
case big.Int:
tmpJson := fmt.Sprintf(
`{"int":%s}`,
v.String(),
)
return []byte(tmpJson), nil
case int, uint, uint64, int64:
tmpJsonObj["int"] = v
case bool:
Expand Down
16 changes: 16 additions & 0 deletions cbor/value_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"encoding/hex"
"encoding/json"
"fmt"
"math/big"
"reflect"
"strings"
"testing"
Expand Down Expand Up @@ -70,6 +71,15 @@ var testDefs = []struct {
},
expectedAstJson: `{"map":[{"k":{"int":1},"v":{"list":[{"int":2}]}},{"k":{"int":3},"v":{"list":[{"int":4}]}}]}`,
},
// [22318265904693663008365, 8535038193994223137511702528]
{
cborHex: "82C24A04B9E028911409DC866DC24C1B9404A39BD8000000000000",
expectedObject: []any{
*(new(big.Int).SetBytes(test.DecodeHexString("04B9E028911409DC866D"))),
*(new(big.Int).SetBytes(test.DecodeHexString("1B9404A39BD8000000000000"))),
},
expectedAstJson: `{"list":[{"int":22318265904693663008365},{"int":8535038193994223137511702528}]}`,
},
}

func TestValueDecode(t *testing.T) {
Expand Down Expand Up @@ -198,6 +208,12 @@ func TestLazyValueMarshalJSON(t *testing.T) {
strings.ToLower(testDef.cborHex),
testDef.expectedAstJson,
)
if testDef.expectedObject == nil {
fullExpectedJson = fmt.Sprintf(
`{"cbor":"%s"}`,
strings.ToLower(testDef.cborHex),
)
}
if !test.JsonStringsEqual(jsonData, []byte(fullExpectedJson)) {
t.Fatalf("CBOR did not marshal to expected JSON\n got: %s\n wanted: %s", jsonData, fullExpectedJson)
}
Expand Down

0 comments on commit 4e6a58d

Please sign in to comment.