diff --git a/cid.go b/cid.go index d88b661..52e9932 100644 --- a/cid.go +++ b/cid.go @@ -290,36 +290,16 @@ func uvError(read int) error { // Please use decode when parsing a regular Cid string, as Cast does not // expect multibase-encoded data. Cast accepts the output of Cid.Bytes(). func Cast(data []byte) (Cid, error) { - if len(data) == 34 && data[0] == 18 && data[1] == 32 { - h, err := mh.Cast(data) - if err != nil { - return Undef, err - } - - return NewCidV0(h), nil - } - - vers, n := binary.Uvarint(data) - if err := uvError(n); err != nil { - return Undef, err - } - - if vers != 1 { - return Undef, fmt.Errorf("expected 1 as the cid version number, got: %d", vers) - } - - _, cn := binary.Uvarint(data[n:]) - if err := uvError(cn); err != nil { - return Undef, err - } - - rest := data[n+cn:] - h, err := mh.Cast(rest) + nr, c, err := CidFromBytes(data) if err != nil { return Undef, err } - return Cid{string(data[0 : n+cn+len(h)])}, nil + if nr != len(data) { + return Undef, fmt.Errorf("trailing bytes in data buffer passed to cid Cast") + } + + return c, nil } // UnmarshalBinary is equivalent to Cast(). It implements the @@ -601,3 +581,42 @@ func PrefixFromBytes(buf []byte) (Prefix, error) { MhLength: int(mhlen), }, nil } + +func CidFromBytes(data []byte) (int, Cid, error) { + if len(data) > 2 && data[0] == 18 && data[1] == 32 { + if len(data) < 34 { + return 0, Undef, fmt.Errorf("not enough bytes for cid v0") + } + + h, err := mh.Cast(data[:34]) + if err != nil { + return 0, Undef, err + } + + return 34, NewCidV0(h), nil + } + + vers, n := binary.Uvarint(data) + if err := uvError(n); err != nil { + return 0, Undef, err + } + + if vers != 1 { + return 0, Undef, fmt.Errorf("expected 1 as the cid version number, got: %d", vers) + } + + _, cn := binary.Uvarint(data[n:]) + if err := uvError(cn); err != nil { + return 0, Undef, err + } + + mhr := mh.NewReader(bytes.NewReader(data[n+cn:])) + h, err := mhr.ReadMultihash() + if err != nil { + return 0, Undef, err + } + + l := n + cn + len(h) + + return l, Cid{string(data[0:l])}, nil +}