-
Notifications
You must be signed in to change notification settings - Fork 50
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Intended to replace github.com/ipfs/go-ipld-format#ErrNotFound * A new IsNotFound() that uses feature detection rather than type checking so it's compatible with old and new forms. Ref: ipld/go-car#363 Ref: #493
- Loading branch information
Showing
3 changed files
with
123 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
package storage | ||
|
||
import "github.com/ipfs/go-cid" | ||
|
||
// compatible with the go-ipld-format ErrNotFound, match against | ||
// interface{NotFound() bool} | ||
// this could go into go-ipld-prime, but for now we'll just exercise the | ||
// feature-test pattern | ||
|
||
// ErrNotFound is a 404, but for block storage systems. It is returned when | ||
// a block is not found. The Key is typically the binary form of a CID | ||
// (CID#KeyString()). | ||
// | ||
// ErrNotFound implements `interface{NotFound() bool}`, which makes it roughly | ||
// compatible with the legacy github.com/ipfs/go-ipld-format#ErrNotFound. | ||
// The IsNotFound() function here will test for this and therefore be compatible | ||
// with this ErrNotFound, and the legacy ErrNotFound. The same is not true for | ||
// the legacy github.com/ipfs/go-ipld-format#IsNotFound. | ||
type ErrNotFound struct { | ||
Key string | ||
} | ||
|
||
// NewErrNotFound is a convenience factory that creates a new ErrNotFound error | ||
// from a CID. | ||
func NewErrNotFound(c cid.Cid) ErrNotFound { | ||
return ErrNotFound{Key: c.KeyString()} | ||
} | ||
|
||
func (e ErrNotFound) Error() string { | ||
if c, err := cid.Cast([]byte(e.Key)); err == nil && c != cid.Undef { | ||
return "ipld: could not find " + c.String() | ||
} | ||
return "ipld: could not find " + e.Key | ||
} | ||
|
||
// NotFound always returns true, and is used to feature-test for ErrNotFound | ||
// errors. | ||
func (e ErrNotFound) NotFound() bool { | ||
return true | ||
} | ||
|
||
// Is allows errors.Is to work with this error type. | ||
func (e ErrNotFound) Is(err error) bool { | ||
switch err.(type) { | ||
case ErrNotFound: | ||
return true | ||
default: | ||
return false | ||
} | ||
} | ||
|
||
// IsNotFound returns true if the error is a ErrNotFound. As it uses a | ||
// feature-test, it is also compatible with the legacy | ||
// github.com/ipfs/go-ipld-format#ErrNotFound. | ||
func IsNotFound(err error) bool { | ||
if nf, ok := err.(interface{ NotFound() bool }); ok { | ||
return nf.NotFound() | ||
} | ||
return false | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
package storage_test | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/ipfs/go-cid" | ||
"github.com/ipld/go-ipld-prime/storage" | ||
) | ||
|
||
func TestNotFound(t *testing.T) { | ||
nf := storage.ErrNotFound{Key: "foo"} | ||
if !storage.IsNotFound(nf) { | ||
t.Fatal("expected ErrNotFound to be a NotFound error") | ||
} | ||
if nf.Error() != "ipld: could not find foo" { | ||
t.Fatal("unexpected error message") | ||
} | ||
|
||
nf = storage.NewErrNotFound(cid.MustParse("bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi")) | ||
if !storage.IsNotFound(nf) { | ||
t.Fatal("expected ErrNotFound to be a NotFound error") | ||
} | ||
if nf.Error() != "ipld: could not find bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi" { | ||
t.Fatal("unexpected error message") | ||
} | ||
|
||
wnf := &weirdNotFoundError{} | ||
if !storage.IsNotFound(wnf) { | ||
t.Fatal("expected weirdNotFoundError to be a NotFound error") | ||
} | ||
|
||
// a weirder case, this one implements `NotFound()` but it returns false, so | ||
// this shouldn't be a NotFound error | ||
wnnf := &weirdNotNotFoundError{} | ||
if storage.IsNotFound(wnnf) { | ||
t.Fatal("expected weirdNotNotFoundError to NOT be a NotFound error") | ||
} | ||
} | ||
|
||
type weirdNotFoundError struct{} | ||
|
||
func (weirdNotFoundError) NotFound() bool { | ||
return true | ||
} | ||
|
||
func (weirdNotFoundError) Error() string { | ||
return "weird not found error" | ||
} | ||
|
||
type weirdNotNotFoundError struct{} | ||
|
||
func (weirdNotNotFoundError) NotFound() bool { | ||
return false | ||
} | ||
|
||
func (weirdNotNotFoundError) Error() string { | ||
return "weird not NOT found error" | ||
} |