@@ -37,10 +37,32 @@ import (
37
37
// UnsupportedVersionString just holds an error message
38
38
const UnsupportedVersionString = "<unsupported cid version>"
39
39
40
+ // ErrInvalidCid is an error that indicates that a CID is invalid.
41
+ type ErrInvalidCid struct {
42
+ Err error
43
+ }
44
+
45
+ func (e ErrInvalidCid ) Error () string {
46
+ return fmt .Sprintf ("invalid cid: %s" , e .Err )
47
+ }
48
+
49
+ func (e ErrInvalidCid ) Unwrap () error {
50
+ return e .Err
51
+ }
52
+
53
+ func (e ErrInvalidCid ) Is (err error ) bool {
54
+ switch err .(type ) {
55
+ case ErrInvalidCid , * ErrInvalidCid :
56
+ return true
57
+ default :
58
+ return false
59
+ }
60
+ }
61
+
40
62
var (
41
63
// ErrCidTooShort means that the cid passed to decode was not long
42
64
// enough to be a valid Cid
43
- ErrCidTooShort = errors .New ("cid too short" )
65
+ ErrCidTooShort = ErrInvalidCid { errors .New ("cid too short" )}
44
66
45
67
// ErrInvalidEncoding means that selected encoding is not supported
46
68
// by this Cid version
@@ -90,10 +112,10 @@ func tryNewCidV0(mhash mh.Multihash) (Cid, error) {
90
112
// incorrectly detect it as CidV1 in the Version() method
91
113
dec , err := mh .Decode (mhash )
92
114
if err != nil {
93
- return Undef , err
115
+ return Undef , ErrInvalidCid { err }
94
116
}
95
117
if dec .Code != mh .SHA2_256 || dec .Length != 32 {
96
- return Undef , fmt .Errorf ("invalid hash for cidv0 %d-%d" , dec .Code , dec .Length )
118
+ return Undef , ErrInvalidCid { fmt .Errorf ("invalid hash for cidv0 %d-%d" , dec .Code , dec .Length )}
97
119
}
98
120
return Cid {string (mhash )}, nil
99
121
}
@@ -177,7 +199,7 @@ func Parse(v interface{}) (Cid, error) {
177
199
case Cid :
178
200
return v2 , nil
179
201
default :
180
- return Undef , fmt .Errorf ("can't parse %+v as Cid" , v2 )
202
+ return Undef , ErrInvalidCid { fmt .Errorf ("can't parse %+v as Cid" , v2 )}
181
203
}
182
204
}
183
205
@@ -210,15 +232,15 @@ func Decode(v string) (Cid, error) {
210
232
if len (v ) == 46 && v [:2 ] == "Qm" {
211
233
hash , err := mh .FromB58String (v )
212
234
if err != nil {
213
- return Undef , err
235
+ return Undef , ErrInvalidCid { err }
214
236
}
215
237
216
238
return tryNewCidV0 (hash )
217
239
}
218
240
219
241
_ , data , err := mbase .Decode (v )
220
242
if err != nil {
221
- return Undef , err
243
+ return Undef , ErrInvalidCid { err }
222
244
}
223
245
224
246
return Cast (data )
@@ -240,7 +262,7 @@ func ExtractEncoding(v string) (mbase.Encoding, error) {
240
262
// check encoding is valid
241
263
_ , err := mbase .NewEncoder (encoding )
242
264
if err != nil {
243
- return - 1 , err
265
+ return - 1 , ErrInvalidCid { err }
244
266
}
245
267
246
268
return encoding , nil
@@ -260,11 +282,11 @@ func ExtractEncoding(v string) (mbase.Encoding, error) {
260
282
func Cast (data []byte ) (Cid , error ) {
261
283
nr , c , err := CidFromBytes (data )
262
284
if err != nil {
263
- return Undef , err
285
+ return Undef , ErrInvalidCid { err }
264
286
}
265
287
266
288
if nr != len (data ) {
267
- return Undef , fmt .Errorf ("trailing bytes in data buffer passed to cid Cast" )
289
+ return Undef , ErrInvalidCid { fmt .Errorf ("trailing bytes in data buffer passed to cid Cast" )}
268
290
}
269
291
270
292
return c , nil
@@ -434,28 +456,28 @@ func (c Cid) Equals(o Cid) bool {
434
456
// UnmarshalJSON parses the JSON representation of a Cid.
435
457
func (c * Cid ) UnmarshalJSON (b []byte ) error {
436
458
if len (b ) < 2 {
437
- return fmt .Errorf ("invalid cid json blob" )
459
+ return ErrInvalidCid { fmt .Errorf ("invalid cid json blob" )}
438
460
}
439
461
obj := struct {
440
462
CidTarget string `json:"/"`
441
463
}{}
442
464
objptr := & obj
443
465
err := json .Unmarshal (b , & objptr )
444
466
if err != nil {
445
- return err
467
+ return ErrInvalidCid { err }
446
468
}
447
469
if objptr == nil {
448
470
* c = Cid {}
449
471
return nil
450
472
}
451
473
452
474
if obj .CidTarget == "" {
453
- return fmt .Errorf ("cid was incorrectly formatted" )
475
+ return ErrInvalidCid { fmt .Errorf ("cid was incorrectly formatted" )}
454
476
}
455
477
456
478
out , err := Decode (obj .CidTarget )
457
479
if err != nil {
458
- return err
480
+ return ErrInvalidCid { err }
459
481
}
460
482
461
483
* c = out
@@ -542,12 +564,12 @@ func (p Prefix) Sum(data []byte) (Cid, error) {
542
564
if p .Version == 0 && (p .MhType != mh .SHA2_256 ||
543
565
(p .MhLength != 32 && p .MhLength != - 1 )) {
544
566
545
- return Undef , fmt .Errorf ("invalid v0 prefix" )
567
+ return Undef , ErrInvalidCid { fmt .Errorf ("invalid v0 prefix" )}
546
568
}
547
569
548
570
hash , err := mh .Sum (data , p .MhType , length )
549
571
if err != nil {
550
- return Undef , err
572
+ return Undef , ErrInvalidCid { err }
551
573
}
552
574
553
575
switch p .Version {
@@ -556,7 +578,7 @@ func (p Prefix) Sum(data []byte) (Cid, error) {
556
578
case 1 :
557
579
return NewCidV1 (p .Codec , hash ), nil
558
580
default :
559
- return Undef , fmt .Errorf ("invalid cid version" )
581
+ return Undef , ErrInvalidCid { fmt .Errorf ("invalid cid version" )}
560
582
}
561
583
}
562
584
@@ -586,22 +608,22 @@ func PrefixFromBytes(buf []byte) (Prefix, error) {
586
608
r := bytes .NewReader (buf )
587
609
vers , err := varint .ReadUvarint (r )
588
610
if err != nil {
589
- return Prefix {}, err
611
+ return Prefix {}, ErrInvalidCid { err }
590
612
}
591
613
592
614
codec , err := varint .ReadUvarint (r )
593
615
if err != nil {
594
- return Prefix {}, err
616
+ return Prefix {}, ErrInvalidCid { err }
595
617
}
596
618
597
619
mhtype , err := varint .ReadUvarint (r )
598
620
if err != nil {
599
- return Prefix {}, err
621
+ return Prefix {}, ErrInvalidCid { err }
600
622
}
601
623
602
624
mhlen , err := varint .ReadUvarint (r )
603
625
if err != nil {
604
- return Prefix {}, err
626
+ return Prefix {}, ErrInvalidCid { err }
605
627
}
606
628
607
629
return Prefix {
@@ -615,34 +637,34 @@ func PrefixFromBytes(buf []byte) (Prefix, error) {
615
637
func CidFromBytes (data []byte ) (int , Cid , error ) {
616
638
if len (data ) > 2 && data [0 ] == mh .SHA2_256 && data [1 ] == 32 {
617
639
if len (data ) < 34 {
618
- return 0 , Undef , fmt .Errorf ("not enough bytes for cid v0" )
640
+ return 0 , Undef , ErrInvalidCid { fmt .Errorf ("not enough bytes for cid v0" )}
619
641
}
620
642
621
643
h , err := mh .Cast (data [:34 ])
622
644
if err != nil {
623
- return 0 , Undef , err
645
+ return 0 , Undef , ErrInvalidCid { err }
624
646
}
625
647
626
648
return 34 , Cid {string (h )}, nil
627
649
}
628
650
629
651
vers , n , err := varint .FromUvarint (data )
630
652
if err != nil {
631
- return 0 , Undef , err
653
+ return 0 , Undef , ErrInvalidCid { err }
632
654
}
633
655
634
656
if vers != 1 {
635
- return 0 , Undef , fmt .Errorf ("expected 1 as the cid version number, got: %d" , vers )
657
+ return 0 , Undef , ErrInvalidCid { fmt .Errorf ("expected 1 as the cid version number, got: %d" , vers )}
636
658
}
637
659
638
660
_ , cn , err := varint .FromUvarint (data [n :])
639
661
if err != nil {
640
- return 0 , Undef , err
662
+ return 0 , Undef , ErrInvalidCid { err }
641
663
}
642
664
643
665
mhnr , _ , err := mh .MHFromBytes (data [n + cn :])
644
666
if err != nil {
645
- return 0 , Undef , err
667
+ return 0 , Undef , ErrInvalidCid { err }
646
668
}
647
669
648
670
l := n + cn + mhnr
@@ -705,32 +727,32 @@ func CidFromReader(r io.Reader) (int, Cid, error) {
705
727
// The varint package wants a io.ByteReader, so we must wrap our io.Reader.
706
728
vers , err := varint .ReadUvarint (br )
707
729
if err != nil {
708
- return len (br .dst ), Undef , err
730
+ return len (br .dst ), Undef , ErrInvalidCid { err }
709
731
}
710
732
711
733
// If we have a CIDv0, read the rest of the bytes and cast the buffer.
712
734
if vers == mh .SHA2_256 {
713
735
if n , err := io .ReadFull (r , br .dst [1 :34 ]); err != nil {
714
- return len (br .dst ) + n , Undef , err
736
+ return len (br .dst ) + n , Undef , ErrInvalidCid { err }
715
737
}
716
738
717
739
br .dst = br .dst [:34 ]
718
740
h , err := mh .Cast (br .dst )
719
741
if err != nil {
720
- return len (br .dst ), Undef , err
742
+ return len (br .dst ), Undef , ErrInvalidCid { err }
721
743
}
722
744
723
745
return len (br .dst ), Cid {string (h )}, nil
724
746
}
725
747
726
748
if vers != 1 {
727
- return len (br .dst ), Undef , fmt .Errorf ("expected 1 as the cid version number, got: %d" , vers )
749
+ return len (br .dst ), Undef , ErrInvalidCid { fmt .Errorf ("expected 1 as the cid version number, got: %d" , vers )}
728
750
}
729
751
730
752
// CID block encoding multicodec.
731
753
_ , err = varint .ReadUvarint (br )
732
754
if err != nil {
733
- return len (br .dst ), Undef , err
755
+ return len (br .dst ), Undef , ErrInvalidCid { err }
734
756
}
735
757
736
758
// We could replace most of the code below with go-multihash's ReadMultihash.
@@ -741,19 +763,19 @@ func CidFromReader(r io.Reader) (int, Cid, error) {
741
763
// Multihash hash function code.
742
764
_ , err = varint .ReadUvarint (br )
743
765
if err != nil {
744
- return len (br .dst ), Undef , err
766
+ return len (br .dst ), Undef , ErrInvalidCid { err }
745
767
}
746
768
747
769
// Multihash digest length.
748
770
mhl , err := varint .ReadUvarint (br )
749
771
if err != nil {
750
- return len (br .dst ), Undef , err
772
+ return len (br .dst ), Undef , ErrInvalidCid { err }
751
773
}
752
774
753
775
// Refuse to make large allocations to prevent OOMs due to bugs.
754
776
const maxDigestAlloc = 32 << 20 // 32MiB
755
777
if mhl > maxDigestAlloc {
756
- return len (br .dst ), Undef , fmt .Errorf ("refusing to allocate %d bytes for a digest" , mhl )
778
+ return len (br .dst ), Undef , ErrInvalidCid { fmt .Errorf ("refusing to allocate %d bytes for a digest" , mhl )}
757
779
}
758
780
759
781
// Fine to convert mhl to int, given maxDigestAlloc.
@@ -772,15 +794,15 @@ func CidFromReader(r io.Reader) (int, Cid, error) {
772
794
if n , err := io .ReadFull (r , br .dst [prefixLength :cidLength ]); err != nil {
773
795
// We can't use len(br.dst) here,
774
796
// as we've only read n bytes past prefixLength.
775
- return prefixLength + n , Undef , err
797
+ return prefixLength + n , Undef , ErrInvalidCid { err }
776
798
}
777
799
778
800
// This simply ensures the multihash is valid.
779
801
// TODO: consider removing this bit, as it's probably redundant;
780
802
// for now, it helps ensure consistency with CidFromBytes.
781
803
_ , _ , err = mh .MHFromBytes (br .dst [mhStart :])
782
804
if err != nil {
783
- return len (br .dst ), Undef , err
805
+ return len (br .dst ), Undef , ErrInvalidCid { err }
784
806
}
785
807
786
808
return len (br .dst ), Cid {string (br .dst )}, nil
0 commit comments