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 "" } 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) }