Skip to content

Commit 79e75df

Browse files
Merge pull request #95 from ipfs/feat/cid-from-bytes
Add a function to read a cid from an array of bytes
2 parents aa8072e + d93d4ba commit 79e75df

File tree

4 files changed

+80
-26
lines changed

4 files changed

+80
-26
lines changed

cid.go

Lines changed: 43 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -290,36 +290,16 @@ func uvError(read int) error {
290290
// Please use decode when parsing a regular Cid string, as Cast does not
291291
// expect multibase-encoded data. Cast accepts the output of Cid.Bytes().
292292
func Cast(data []byte) (Cid, error) {
293-
if len(data) == 34 && data[0] == 18 && data[1] == 32 {
294-
h, err := mh.Cast(data)
295-
if err != nil {
296-
return Undef, err
297-
}
298-
299-
return NewCidV0(h), nil
300-
}
301-
302-
vers, n := binary.Uvarint(data)
303-
if err := uvError(n); err != nil {
304-
return Undef, err
305-
}
306-
307-
if vers != 1 {
308-
return Undef, fmt.Errorf("expected 1 as the cid version number, got: %d", vers)
309-
}
310-
311-
_, cn := binary.Uvarint(data[n:])
312-
if err := uvError(cn); err != nil {
293+
nr, c, err := CidFromBytes(data)
294+
if err != nil {
313295
return Undef, err
314296
}
315297

316-
rest := data[n+cn:]
317-
h, err := mh.Cast(rest)
318-
if err != nil {
319-
return Undef, err
298+
if nr != len(data) {
299+
return Undef, fmt.Errorf("trailing bytes in data buffer passed to cid Cast")
320300
}
321301

322-
return Cid{string(data[0 : n+cn+len(h)])}, nil
302+
return c, nil
323303
}
324304

325305
// UnmarshalBinary is equivalent to Cast(). It implements the
@@ -607,3 +587,41 @@ func PrefixFromBytes(buf []byte) (Prefix, error) {
607587
MhLength: int(mhlen),
608588
}, nil
609589
}
590+
591+
func CidFromBytes(data []byte) (int, Cid, error) {
592+
if len(data) > 2 && data[0] == 18 && data[1] == 32 {
593+
if len(data) < 34 {
594+
return 0, Undef, fmt.Errorf("not enough bytes for cid v0")
595+
}
596+
597+
h, err := mh.Cast(data[:34])
598+
if err != nil {
599+
return 0, Undef, err
600+
}
601+
602+
return 34, NewCidV0(h), nil
603+
}
604+
605+
vers, n := binary.Uvarint(data)
606+
if err := uvError(n); err != nil {
607+
return 0, Undef, err
608+
}
609+
610+
if vers != 1 {
611+
return 0, Undef, fmt.Errorf("expected 1 as the cid version number, got: %d", vers)
612+
}
613+
614+
_, cn := binary.Uvarint(data[n:])
615+
if err := uvError(cn); err != nil {
616+
return 0, Undef, err
617+
}
618+
619+
mhnr, _, err := mh.MHFromBytes(data[n+cn:])
620+
if err != nil {
621+
return 0, Undef, err
622+
}
623+
624+
l := n + cn + mhnr
625+
626+
return l, Cid{string(data[0:l])}, nil
627+
}

cid_test.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -550,3 +550,37 @@ func BenchmarkStringV1(b *testing.B) {
550550
b.FailNow()
551551
}
552552
}
553+
554+
func TestReadCidsFromBuffer(t *testing.T) {
555+
cidstr := []string{
556+
"bafkreie5qrjvaw64n4tjm6hbnm7fnqvcssfed4whsjqxzslbd3jwhsk3mm",
557+
"Qmf5Qzp6nGBku7CEn2UQx4mgN8TW69YUok36DrGa6NN893",
558+
"zb2rhZi1JR4eNc2jBGaRYJKYM8JEB4ovenym8L1CmFsRAytkz",
559+
}
560+
561+
var cids []Cid
562+
var buf []byte
563+
for _, cs := range cidstr {
564+
c, err := Decode(cs)
565+
if err != nil {
566+
t.Fatal(err)
567+
}
568+
cids = append(cids, c)
569+
buf = append(buf, c.Bytes()...)
570+
}
571+
572+
var cur int
573+
for _, expc := range cids {
574+
n, c, err := CidFromBytes(buf[cur:])
575+
if err != nil {
576+
t.Fatal(err)
577+
}
578+
if c != expc {
579+
t.Fatal("cids mismatched")
580+
}
581+
cur += n
582+
}
583+
if cur != len(buf) {
584+
t.Fatal("had trailing bytes")
585+
}
586+
}

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ module github.com/ipfs/go-cid
22

33
require (
44
github.com/multiformats/go-multibase v0.0.1
5-
github.com/multiformats/go-multihash v0.0.8
5+
github.com/multiformats/go-multihash v0.0.9
66
)
77

88
go 1.13

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ github.com/multiformats/go-multibase v0.0.1 h1:PN9/v21eLywrFWdFNsFKaU04kLJzuYzmr
1212
github.com/multiformats/go-multibase v0.0.1/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/gviWFaSteVbWT51qgs=
1313
github.com/multiformats/go-multihash v0.0.8 h1:wrYcW5yxSi3dU07n5jnuS5PrNwyHy0zRHGVoUugWvXg=
1414
github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew=
15+
github.com/multiformats/go-multihash v0.0.9 h1:aoijQXYYl7Xtb2pUUP68R+ys1TlnlR3eX6wmozr0Hp4=
16+
github.com/multiformats/go-multihash v0.0.9/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew=
1517
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
1618
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
1719
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=

0 commit comments

Comments
 (0)