diff --git a/cbor_gen.go b/cbor_gen.go index d7cf543..8463e1a 100644 --- a/cbor_gen.go +++ b/cbor_gen.go @@ -5,18 +5,19 @@ package hamt import ( "fmt" "io" - "math/big" + "math" + "sort" + cid "github.com/ipfs/go-cid" cbg "github.com/whyrusleeping/cbor-gen" xerrors "golang.org/x/xerrors" + big "math/big" ) -// NOTE: This is a generated file, but it has been modified to encode the -// bitfield big.Int as a byte array. The bitfield is only a big.Int because -// thats a convenient type for the operations we need to perform on it, but it -// is fundamentally an array of bytes (bits) - var _ = xerrors.Errorf +var _ = cid.Undef +var _ = math.E +var _ = sort.Sort var lengthBufNode = []byte{130} @@ -25,29 +26,33 @@ func (t *Node) MarshalCBOR(w io.Writer) error { _, err := w.Write(cbg.CborNull) return err } - if _, err := w.Write(lengthBufNode); err != nil { - return err - } cw := cbg.NewCborWriter(w) + if _, err := cw.Write(lengthBufNode); err != nil { + return err + } + // t.Bitfield (big.Int) (struct) { + if err := cw.CborWriteHeader(cbg.MajTag, 2); err != nil { + return err + } var b []byte if t.Bitfield != nil { b = t.Bitfield.Bytes() } - if err := cw.WriteMajorTypeHeader(cbg.MajByteString, uint64(len(b))); err != nil { + if err := cw.CborWriteHeader(cbg.MajByteString, uint64(len(b))); err != nil { return err } - if _, err := w.Write(b); err != nil { + if _, err := cw.Write(b); err != nil { return err } } // t.Pointers ([]*hamt.Pointer) (slice) - if len(t.Pointers) > cbg.MaxLength { + if uint64(len(t.Pointers)) > cbg.MaxLength { return xerrors.Errorf("Slice value in field t.Pointers was too long") } @@ -55,14 +60,15 @@ func (t *Node) MarshalCBOR(w io.Writer) error { return err } for _, v := range t.Pointers { - if err := v.MarshalCBOR(w); err != nil { + if err := v.MarshalCBOR(cw); err != nil { return err } + } return nil } -func (t *Node) UnmarshalCBOR(r io.Reader) error { +func (t *Node) UnmarshalCBOR(r io.Reader) (err error) { *t = Node{} cr := cbg.NewCborReader(r) @@ -71,6 +77,12 @@ func (t *Node) UnmarshalCBOR(r io.Reader) error { if err != nil { return err } + defer func() { + if err == io.EOF { + err = io.ErrUnexpectedEOF + } + }() + if maj != cbg.MajArray { return fmt.Errorf("cbor input should be of type array") } @@ -86,6 +98,15 @@ func (t *Node) UnmarshalCBOR(r io.Reader) error { return err } + if maj != cbg.MajTag || extra != 2 { + return fmt.Errorf("big ints should be cbor bignums") + } + + maj, extra, err = cr.ReadHeader() + if err != nil { + return err + } + if maj != cbg.MajByteString { return fmt.Errorf("big ints should be tagged cbor byte strings") } @@ -123,15 +144,34 @@ func (t *Node) UnmarshalCBOR(r io.Reader) error { } for i := 0; i < int(extra); i++ { + { + var maj byte + var extra uint64 + var err error + _ = maj + _ = extra + _ = err + + { + + b, err := cr.ReadByte() + if err != nil { + return err + } + if b != cbg.CborNull[0] { + if err := cr.UnreadByte(); err != nil { + return err + } + t.Pointers[i] = new(Pointer) + if err := t.Pointers[i].UnmarshalCBOR(cr); err != nil { + return xerrors.Errorf("unmarshaling t.Pointers[i] pointer: %w", err) + } + } + + } - var v Pointer - if err := v.UnmarshalCBOR(cr); err != nil { - return err } - - t.Pointers[i] = &v } - return nil } @@ -142,14 +182,15 @@ func (t *KV) MarshalCBOR(w io.Writer) error { _, err := w.Write(cbg.CborNull) return err } - if _, err := w.Write(lengthBufKV); err != nil { - return err - } cw := cbg.NewCborWriter(w) + if _, err := cw.Write(lengthBufKV); err != nil { + return err + } + // t.Key ([]uint8) (slice) - if len(t.Key) > cbg.ByteArrayMaxLen { + if uint64(len(t.Key)) > cbg.ByteArrayMaxLen { return xerrors.Errorf("Byte array in field t.Key was too long") } @@ -157,18 +198,18 @@ func (t *KV) MarshalCBOR(w io.Writer) error { return err } - if _, err := w.Write(t.Key[:]); err != nil { + if _, err := cw.Write(t.Key); err != nil { return err } // t.Value (typegen.Deferred) (struct) - if err := t.Value.MarshalCBOR(w); err != nil { + if err := t.Value.MarshalCBOR(cw); err != nil { return err } return nil } -func (t *KV) UnmarshalCBOR(r io.Reader) error { +func (t *KV) UnmarshalCBOR(r io.Reader) (err error) { *t = KV{} cr := cbg.NewCborReader(r) @@ -177,6 +218,12 @@ func (t *KV) UnmarshalCBOR(r io.Reader) error { if err != nil { return err } + defer func() { + if err == io.EOF { + err = io.ErrUnexpectedEOF + } + }() + if maj != cbg.MajArray { return fmt.Errorf("cbor input should be of type array") } @@ -200,12 +247,13 @@ func (t *KV) UnmarshalCBOR(r io.Reader) error { } if extra > 0 { - t.Key = make([]byte, extra) + t.Key = make([]uint8, extra) } - if _, err := io.ReadFull(cr, t.Key[:]); err != nil { + if _, err := io.ReadFull(cr, t.Key); err != nil { return err } + // t.Value (typegen.Deferred) (struct) { diff --git a/go.mod b/go.mod index 7743f26..1df854d 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/ipfs/go-ipld-cbor v0.0.4 github.com/spaolacci/murmur3 v1.1.0 github.com/stretchr/testify v1.7.0 - github.com/whyrusleeping/cbor-gen v0.0.0-20220323183124-98fa8256a799 + github.com/whyrusleeping/cbor-gen v0.0.0-20240202185644-fcdaca49d05c golang.org/x/sync v0.0.0-20210220032951-036812b2e83c golang.org/x/sys v0.15.0 // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 diff --git a/go.sum b/go.sum index f8eaf44..c79045b 100644 --- a/go.sum +++ b/go.sum @@ -65,8 +65,8 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/warpfork/go-wish v0.0.0-20180510122957-5ad1f5abf436 h1:qOpVTI+BrstcjTZLm2Yz/3sOnqkzj3FQoh0g+E5s3Gc= github.com/warpfork/go-wish v0.0.0-20180510122957-5ad1f5abf436/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw= github.com/whyrusleeping/cbor-gen v0.0.0-20200123233031-1cdf64d27158/go.mod h1:Xj/M2wWU+QdTdRbu/L/1dIZY8/Wb2K9pAhtroQuxJJI= -github.com/whyrusleeping/cbor-gen v0.0.0-20220323183124-98fa8256a799 h1:DOOT2B85S0tHoLGTzV+FakaSSihgRCVwZkjqKQP5L/w= -github.com/whyrusleeping/cbor-gen v0.0.0-20220323183124-98fa8256a799/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= +github.com/whyrusleeping/cbor-gen v0.0.0-20240202185644-fcdaca49d05c h1:M1YZPgYCRFLagAt7SLkvw5CRykaIlZJqjk4Crl5fmoQ= +github.com/whyrusleeping/cbor-gen v0.0.0-20240202185644-fcdaca49d05c/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= diff --git a/pointer_cbor.go b/pointer_cbor.go deleted file mode 100644 index 185c5ef..0000000 --- a/pointer_cbor.go +++ /dev/null @@ -1,103 +0,0 @@ -package hamt - -import ( - "fmt" - "io" - - cid "github.com/ipfs/go-cid" - cbg "github.com/whyrusleeping/cbor-gen" -) - -// implemented as a kinded union - a "Pointer" is either a Link (child node) or -// an Array (bucket) - -func (t *Pointer) MarshalCBOR(w io.Writer) error { - if t.Link != cid.Undef && len(t.KVs) > 0 { - return fmt.Errorf("hamt Pointer cannot have both a link and KVs") - } - - cw := cbg.NewCborWriter(w) - - if t.Link != cid.Undef { - if err := cbg.WriteCid(cw, t.Link); err != nil { - return err - } - } else { - if err := cw.WriteMajorTypeHeader(cbg.MajArray, uint64(len(t.KVs))); err != nil { - return err - } - - for _, kv := range t.KVs { - if err := kv.MarshalCBOR(cw); err != nil { - return err - } - } - } - - return nil -} - -func (t *Pointer) UnmarshalCBOR(r io.Reader) error { - cr := cbg.NewCborReader(r) - - maj, extra, err := cr.ReadHeader() - if err != nil { - return err - } - - if maj == cbg.MajTag { - if extra != 42 { - return fmt.Errorf("expected tag 42 for child node link") - } - - ba, err := cbg.ReadByteArray(cr, 512) - if err != nil { - return err - } - - c, err := bufToCid(ba) - if err != nil { - return err - } - - t.Link = c - return nil - } else if maj == cbg.MajArray { - length := extra - - if length > 32 { - return fmt.Errorf("KV array in CBOR input for pointer was too long") - } - - t.KVs = make([]*KV, length) - for i := 0; i < int(length); i++ { - var kv KV - if err := kv.UnmarshalCBOR(cr); err != nil { - return err - } - - t.KVs[i] = &kv - } - - return nil - } else { - return fmt.Errorf("expected CBOR child node link or array") - } -} - -// from https://github.com/whyrusleeping/cbor-gen/blob/211df3b9e24c6e0d0c338b440e6ab4ab298505b2/utils.go#L530 -func bufToCid(buf []byte) (cid.Cid, error) { - if len(buf) == 0 { - return cid.Undef, fmt.Errorf("undefined CID") - } - - if len(buf) < 2 { - return cid.Undef, fmt.Errorf("DAG-CBOR serialized CIDs must have at least two bytes") - } - - if buf[0] != 0 { - return cid.Undef, fmt.Errorf("DAG-CBOR serialized CIDs must have binary multibase") - } - - return cid.Cast(buf[1:]) -}