integrate new bigint encoding into refmt atlas (temporary)

This commit is contained in:
whyrusleeping 2019-09-25 21:03:13 -07:00
parent 5f31544faa
commit 9f654ab893

View File

@ -17,18 +17,14 @@ import (
const BigIntMaxSerializedLen = 128 // is this big enough? or too big? const BigIntMaxSerializedLen = 128 // is this big enough? or too big?
func init() { func init() {
cbor.RegisterCborType(atlas.BuildEntry(BigInt{}).UseTag(2).Transform(). cbor.RegisterCborType(atlas.BuildEntry(BigInt{}).Transform().
TransformMarshal(atlas.MakeMarshalTransformFunc( TransformMarshal(atlas.MakeMarshalTransformFunc(
func(i BigInt) ([]byte, error) { func(i BigInt) ([]byte, error) {
if i.Int == nil { return i.cborBytes(), nil
return []byte{}, nil
}
return i.Bytes(), nil
})). })).
TransformUnmarshal(atlas.MakeUnmarshalTransformFunc( TransformUnmarshal(atlas.MakeUnmarshalTransformFunc(
func(x []byte) (BigInt, error) { func(x []byte) (BigInt, error) {
return BigFromBytes(x), nil return fromCborBytes(x)
})). })).
Complete()) Complete())
} }
@ -117,20 +113,49 @@ func (bi *BigInt) UnmarshalJSON(b []byte) error {
return nil return nil
} }
func (bi *BigInt) cborBytes() []byte {
if bi.Int == nil {
return []byte{}
}
switch {
case bi.Sign() == 0:
return []byte{}
case bi.Sign() > 0:
return append([]byte{0}, bi.Bytes()...)
case bi.Sign() < 0:
return append([]byte{1}, bi.Bytes()...)
}
panic("unreachable")
}
func fromCborBytes(buf []byte) (BigInt, error) {
var negative bool
switch buf[0] {
case 0:
negative = false
case 1:
negative = true
default:
return EmptyInt, fmt.Errorf("big int prefix should be either 0 or 1, got %d", buf[0])
}
i := big.NewInt(0).SetBytes(buf[1:])
if negative {
i.Neg(i)
}
return BigInt{i}, nil
}
func (bi *BigInt) MarshalCBOR(w io.Writer) error { func (bi *BigInt) MarshalCBOR(w io.Writer) error {
if bi.Int == nil { if bi.Int == nil {
zero := NewInt(0) zero := NewInt(0)
return zero.MarshalCBOR(w) return zero.MarshalCBOR(w)
} }
var enc []byte enc := bi.cborBytes()
switch {
case bi.Sign() == 0:
case bi.Sign() > 0:
enc = append([]byte{0}, bi.Bytes()...)
case bi.Sign() < 0:
enc = append([]byte{1}, bi.Bytes()...)
}
header := cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(enc))) header := cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(enc)))
if _, err := w.Write(header); err != nil { if _, err := w.Write(header); err != nil {
@ -168,20 +193,12 @@ func (bi *BigInt) UnmarshalCBOR(br io.Reader) error {
return err return err
} }
var negative bool i, err := fromCborBytes(buf)
switch buf[0] { if err != nil {
case 0: return err
negative = false
case 1:
negative = true
default:
return fmt.Errorf("big int prefix should be either 0 or 1, got %d", buf[0])
} }
bi.Int = big.NewInt(0).SetBytes(buf[1:]) *bi = i
if negative {
bi.Int.Neg(bi.Int)
}
return nil return nil
} }