Add storage backends and safety checks
This commit is contained in:
128
internal/storage/errors.go
Normal file
128
internal/storage/errors.go
Normal file
@@ -0,0 +1,128 @@
|
||||
package storage
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type ErrorKind string
|
||||
|
||||
const (
|
||||
ErrNotFound ErrorKind = "not_found"
|
||||
ErrAlreadyExist ErrorKind = "already_exists"
|
||||
ErrNotEmpty ErrorKind = "not_empty"
|
||||
ErrInvalidPath ErrorKind = "invalid_path"
|
||||
ErrConflict ErrorKind = "conflict"
|
||||
ErrPermission ErrorKind = "permission"
|
||||
ErrTemporary ErrorKind = "temporary"
|
||||
ErrUnsupported ErrorKind = "unsupported"
|
||||
ErrUnknown ErrorKind = "unknown"
|
||||
)
|
||||
|
||||
const (
|
||||
OpValidatePath = "validate path"
|
||||
OpReadFile = "read file"
|
||||
OpOpenReader = "open reader"
|
||||
OpWriteFile = "write file"
|
||||
OpWriteFrom = "write stream"
|
||||
OpStat = "stat"
|
||||
OpWalk = "walk"
|
||||
OpHasAny = "has any"
|
||||
OpDeleteManagedBundle = "delete managed bundle"
|
||||
OpRegisterBackend = "register backend"
|
||||
OpOpenBackend = "open backend"
|
||||
)
|
||||
|
||||
type Error struct {
|
||||
Op string
|
||||
Backend string
|
||||
Path string
|
||||
Kind ErrorKind
|
||||
Err error
|
||||
}
|
||||
|
||||
func NewError(op, backend, path string, kind ErrorKind, err error) *Error {
|
||||
return &Error{
|
||||
Op: op,
|
||||
Backend: backend,
|
||||
Path: path,
|
||||
Kind: kind,
|
||||
Err: err,
|
||||
}
|
||||
}
|
||||
|
||||
func (e *Error) Error() string {
|
||||
if e == nil {
|
||||
return "<nil>"
|
||||
}
|
||||
message := e.Op
|
||||
if e.Backend != "" {
|
||||
message += " " + e.Backend
|
||||
}
|
||||
if e.Path != "" {
|
||||
message += " " + e.Path
|
||||
}
|
||||
if e.Kind != "" {
|
||||
message += ": " + string(e.Kind)
|
||||
}
|
||||
if e.Err != nil {
|
||||
message += ": " + e.Err.Error()
|
||||
}
|
||||
return message
|
||||
}
|
||||
|
||||
func (e *Error) Unwrap() error {
|
||||
if e == nil {
|
||||
return nil
|
||||
}
|
||||
return e.Err
|
||||
}
|
||||
|
||||
func (e *Error) Is(target error) bool {
|
||||
var targetError *Error
|
||||
if !errors.As(target, &targetError) {
|
||||
return false
|
||||
}
|
||||
return targetError.Kind == "" || e.Kind == targetError.Kind
|
||||
}
|
||||
|
||||
func Errorf(op, backend, path string, kind ErrorKind, format string, args ...any) *Error {
|
||||
return NewError(op, backend, path, kind, fmt.Errorf(format, args...))
|
||||
}
|
||||
|
||||
func IsKind(err error, kind ErrorKind) bool {
|
||||
var storageErr *Error
|
||||
return errors.As(err, &storageErr) && storageErr.Kind == kind
|
||||
}
|
||||
|
||||
func IsNotFound(err error) bool {
|
||||
return IsKind(err, ErrNotFound)
|
||||
}
|
||||
|
||||
func IsAlreadyExists(err error) bool {
|
||||
return IsKind(err, ErrAlreadyExist)
|
||||
}
|
||||
|
||||
func IsNotEmpty(err error) bool {
|
||||
return IsKind(err, ErrNotEmpty)
|
||||
}
|
||||
|
||||
func IsInvalidPath(err error) bool {
|
||||
return IsKind(err, ErrInvalidPath)
|
||||
}
|
||||
|
||||
func IsConflict(err error) bool {
|
||||
return IsKind(err, ErrConflict)
|
||||
}
|
||||
|
||||
func IsPermission(err error) bool {
|
||||
return IsKind(err, ErrPermission)
|
||||
}
|
||||
|
||||
func IsTemporary(err error) bool {
|
||||
return IsKind(err, ErrTemporary)
|
||||
}
|
||||
|
||||
func IsUnsupported(err error) bool {
|
||||
return IsKind(err, ErrUnsupported)
|
||||
}
|
||||
Reference in New Issue
Block a user