aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--util/errors.go107
-rw-r--r--util/util.go74
-rw-r--r--util/util_test.go2
3 files changed, 102 insertions, 81 deletions
diff --git a/util/errors.go b/util/errors.go
index bd63ac8..e5eea4b 100644
--- a/util/errors.go
+++ b/util/errors.go
@@ -21,25 +21,94 @@ package util
import (
"fmt"
+ "io"
"log"
"os"
)
-// InvalidInputF creates an error that should indicate either bad input from a
-// caller of a public library function or bad user input.
-func InvalidInputF(format string, a ...interface{}) error {
- return fmt.Errorf("invalid input: "+format, a...)
+// ErrReader wraps an io.Reader, passing along calls to Read() until a read
+// fails. Then, the error is stored, and all subsequent calls to Read() do
+// nothing. This allows you to write code which has many subsequent reads and
+// do all of the error checking at the end. For example:
+//
+// r := NewErrReader(reader)
+// r.Read(foo)
+// r.Read(bar)
+// r.Read(baz)
+// if r.Err() != nil {
+// // Handle error
+// }
+//
+// Taken from https://blog.golang.org/errors-are-values by Rob Pike.
+type ErrReader struct {
+ r io.Reader
+ err error
+}
+
+// NewErrReader creates an ErrReader which wraps the provided reader.
+func NewErrReader(reader io.Reader) *ErrReader {
+ return &ErrReader{r: reader, err: nil}
+}
+
+// Read runs ReadFull on the wrapped reader if no errors have occurred.
+// Otherwise, the previous error is just returned and no reads are attempted.
+func (e *ErrReader) Read(p []byte) (n int, err error) {
+ if e.err == nil {
+ n, e.err = io.ReadFull(e.r, p)
+ }
+ return n, e.err
+}
+
+// Err returns the first encountered err (or nil if no errors occurred).
+func (e *ErrReader) Err() error {
+ return e.err
+}
+
+// ErrWriter works exactly like ErrReader, except with io.Writer.
+type ErrWriter struct {
+ w io.Writer
+ err error
+}
+
+// NewErrWriter creates an ErrWriter which wraps the provided reader.
+func NewErrWriter(writer io.Writer) *ErrWriter {
+ return &ErrWriter{w: writer, err: nil}
+}
+
+// Write runs the wrapped writer's Write if no errors have occurred. Otherwise,
+// the previous error is just returned and no writes are attempted.
+func (e *ErrWriter) Write(p []byte) (n int, err error) {
+ if e.err == nil {
+ n, e.err = e.w.Write(p)
+ }
+ return n, e.err
+}
+
+// Err returns the first encountered err (or nil if no errors occurred).
+func (e *ErrWriter) Err() error {
+ return e.err
+}
+
+// InvalidInput is an error that should indicate either bad input from a caller
+// of a public package function.
+type InvalidInput string
+
+func (i InvalidInput) Error() string {
+ return "invalid input: " + string(i)
}
// InvalidLengthError indicates name should have had length expected.
-func InvalidLengthError(name string, expected int, actual int) error {
- return InvalidInputF("expected %s of length %d, actual length was %d", name, expected, actual)
+func InvalidLengthError(name string, expected int, actual int) InvalidInput {
+ message := fmt.Sprintf("length of %s: expected=%d, actual=%d", name, expected, actual)
+ return InvalidInput(message)
}
-// SystemErrorF creates an error that should indicate something has gone wrong
-// in the underlying system (syscall failure, bad ioctl, etc...).
-func SystemErrorF(format string, a ...interface{}) error {
- return fmt.Errorf("system error: "+format, a...)
+// SystemError is an error that should indicate something has gone wrong in the
+// underlying system (syscall failure, bad ioctl, etc...).
+type SystemError string
+
+func (s SystemError) Error() string {
+ return "system error: " + string(s)
}
// NeverError panics if a non-nil error is passed in. It should be used to check
@@ -50,16 +119,20 @@ func NeverError(err error) {
}
}
-// UnderlyingError returns the underlying error for known os error types.
-// From: src/os/error.go
+// UnderlyingError returns the underlying error for known os error types and
+// logs the full error. From: src/os/error.go
func UnderlyingError(err error) error {
- switch err := err.(type) {
+ var newErr error
+ switch typedErr := err.(type) {
case *os.PathError:
- return err.Err
+ newErr = typedErr.Err
case *os.LinkError:
- return err.Err
+ newErr = typedErr.Err
case *os.SyscallError:
- return err.Err
+ newErr = typedErr.Err
+ default:
+ return err
}
- return err
+ log.Print(err)
+ return newErr
}
diff --git a/util/util.go b/util/util.go
index dc1b85d..2f20151 100644
--- a/util/util.go
+++ b/util/util.go
@@ -24,74 +24,14 @@
package util
import (
- "io"
"unsafe"
)
-// ErrReader wraps an io.Reader, passing along calls to Read() until a read
-// fails. Then, the error is stored, and all subsequent calls to Read() do
-// nothing. This allows you to write code which has many subsequent reads and
-// do all of the error checking at the end. For example:
-//
-// r := NewErrReader(reader)
-// r.Read(foo)
-// io.ReadFull(r, bar)
-// if r.Err() != nil {
-// // Handle error
-// }
-//
-// Taken from https://blog.golang.org/errors-are-values by Rob Pike.
-type ErrReader struct {
- r io.Reader
- err error
-}
-
-// NewErrReader creates an ErrReader which wraps the provided reader.
-func NewErrReader(reader io.Reader) *ErrReader {
- return &ErrReader{r: reader, err: nil}
-}
-
-// Read runs ReadFull on the wrapped reader if no errors have occurred.
-// Otherwise, the previous error is just returned and no reads are attempted.
-func (e *ErrReader) Read(p []byte) (n int, err error) {
- if e.err == nil {
- n, e.err = io.ReadFull(e.r, p)
- }
- return n, e.err
-}
-
-// Err returns the first encountered err (or nil if no errors occurred).
-func (e *ErrReader) Err() error {
- return e.err
-}
-
-// ErrWriter works exactly like ErrReader, except with io.Writer.
-type ErrWriter struct {
- w io.Writer
- err error
-}
-
-// NewErrWriter creates an ErrWriter which wraps the provided reader.
-func NewErrWriter(writer io.Writer) *ErrWriter {
- return &ErrWriter{w: writer, err: nil}
-}
-
-// Write runs the wrapped writer's Write if no errors have occurred. Otherwise,
-// the previous error is just returned and no writes are attempted.
-func (e *ErrWriter) Write(p []byte) (n int, err error) {
- if e.err == nil {
- n, e.err = e.w.Write(p)
- }
- return n, e.err
-}
-
-// Err returns the first encountered err (or nil if no errors occurred).
-func (e *ErrWriter) Err() error {
- return e.err
-}
-
// Ptr converts an Go byte array to a pointer to the start of the array.
func Ptr(slice []byte) unsafe.Pointer {
+ if len(slice) == 0 {
+ return nil
+ }
return unsafe.Pointer(&slice[0])
}
@@ -124,3 +64,11 @@ func MinInt(a, b int) int {
}
return b
}
+
+// MinInt64 returns the lesser of a and b.
+func MinInt64(a, b int64) int64 {
+ if a < b {
+ return a
+ }
+ return b
+}
diff --git a/util/util_test.go b/util/util_test.go
index 65541b3..33ce2ff 100644
--- a/util/util_test.go
+++ b/util/util_test.go
@@ -44,7 +44,7 @@ func TestNeverErrorPanic(t *testing.T) {
}
}()
- err := SystemErrorF("Hello")
+ err := SystemError("Hello")
NeverError(err)
}