Skip to content

Commit

Permalink
Merge pull request #117 from shogo82148/support-bignum-edn
Browse files Browse the repository at this point in the history
Support bignum edn
  • Loading branch information
shogo82148 authored Nov 4, 2023
2 parents ba162df + ba6212b commit 52f25b3
Show file tree
Hide file tree
Showing 2 changed files with 115 additions and 26 deletions.
74 changes: 67 additions & 7 deletions edn.go
Original file line number Diff line number Diff line change
Expand Up @@ -486,18 +486,20 @@ func (s *ednDecState) tryToDecodeInteger(str string, ind encodingIndicator) bool
if i.IsUint64() {
s.writeUint(majorTypePositiveInt, ind, i.Uint64())
} else {
// TODO: support big.Int
s.err = newSemanticError("cbor: unsupported big.Int")
return true
s.writeByte(0xc2) // tag 2 (positive bignum)
data := i.Bytes()
s.writeUint(majorTypeBytes, -1, uint64(len(data)))
s.buf.Write(data)
}
} else {
i.Not(i)
if i.IsUint64() {
s.writeUint(majorTypeNegativeInt, ind, i.Uint64())
} else {
// TODO: support big.Int
s.err = newSemanticError("cbor: unsupported big.Int")
return true
s.writeByte(0xc3) // tag 3 (negative bignum)
data := i.Bytes()
s.writeUint(majorTypeBytes, -1, uint64(len(data)))
s.buf.Write(data)
}
}
return true
Expand Down Expand Up @@ -1564,8 +1566,16 @@ func (s *ednEncState) encode() {
}
s.buf.WriteByte('}')

// positive big int
case 0xc2:
s.convertBigInt(1)

// negative big int
case 0xc3:
s.convertBigInt(-1)

// tags
case 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7:
case 0xc0, 0xc1, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7:
s.convertTag(uint64(typ & 0x1f))

// 1 byte tag
Expand Down Expand Up @@ -1785,3 +1795,53 @@ func (s *ednEncState) convertFloat(v float64) {
}
s.buf.WriteString(str)
}

func (s *ednEncState) convertBigInt(sign int) {
i := new(big.Int)

tye, err := s.readByte()
if err != nil {
s.err = err
return
}

switch tye {
case 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57:
n := int(tye & 0x1f)
i.SetBytes(s.data[s.off : s.off+n])
s.off += n
case 0x58:
n, err := s.readByte()
if err != nil {
s.err = err
}
i.SetBytes(s.data[s.off : s.off+int(n)])
s.off += int(n)
case 0x59:
n, err := s.readUint16()
if err != nil {
s.err = err
}
i.SetBytes(s.data[s.off : s.off+int(n)])
s.off += int(n)
case 0x5a:
n, err := s.readUint32()
if err != nil {
s.err = err
}
i.SetBytes(s.data[s.off : s.off+int(n)])
s.off += int(n)
case 0x5b:
n, err := s.readUint64()
if err != nil {
s.err = err
}
i.SetBytes(s.data[s.off : s.off+int(n)])
}

if sign < 0 {
i.Not(i)
}

s.buf.WriteString(i.String())
}
67 changes: 48 additions & 19 deletions edn_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -350,20 +350,18 @@ func TestDecodeEDN(t *testing.T) {
in: "18446744073709551615",
out: RawMessage{0x1b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
},
// TODO: fix this
// {
// in: "18446744073709551616",
// out: RawMessage{0xc2, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
// },
{
in: "18446744073709551616",
out: RawMessage{0xc2, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
},
{
in: "-18446744073709551616",
out: RawMessage{0x3b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
},
// TODO: fix this
// {
// in: "-18446744073709551617",
// out: RawMessage{0xc3, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
// },
{
in: "-18446744073709551617",
out: RawMessage{0xc3, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
},
{
in: "-1",
out: RawMessage{0x20},
Expand Down Expand Up @@ -910,6 +908,38 @@ func TestEncodeEDN(t *testing.T) {
},
out: `1(1363896240)`,
},
{
in: RawMessage{
0xc2,
0x58, 0x09,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
},
out: `18446744073709551616`,
},
{
in: RawMessage{
0xc2,
0x59, 0x00, 0x09,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
},
out: `18446744073709551616`,
},
{
in: RawMessage{
0xc2,
0x5a, 0x00, 0x00, 0x00, 0x09,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
},
out: `18446744073709551616`,
},
{
in: RawMessage{
0xc2,
0x5b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
},
out: `18446744073709551616`,
},

// simple values
{
Expand Down Expand Up @@ -1012,19 +1042,18 @@ func TestEncodeEDN(t *testing.T) {
in: RawMessage{0x1b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
out: `18446744073709551615`,
},
// TODO: fix this
// {
// in: RawMessage{0xc2, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
// out: `18446744073709551616`,
// },
{
in: RawMessage{0xc2, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
out: `18446744073709551616`,
},
{
in: RawMessage{0x3b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
out: `-18446744073709551616`,
},
// {
// in: RawMessage{0xc3, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
// out: `-18446744073709551617`,
// },
{
in: RawMessage{0xc3, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
out: `-18446744073709551617`,
},
{
in: RawMessage{0x20},
out: `-1`,
Expand Down

0 comments on commit 52f25b3

Please sign in to comment.