80 lines
1.6 KiB
Go
80 lines
1.6 KiB
Go
package shortcircuit
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
)
|
|
|
|
// Error indicates that a write was not attempted because
|
|
// an earlier write failed due to Err.
|
|
type Error struct {
|
|
Err error
|
|
}
|
|
|
|
func (a Error) Error() string {
|
|
return fmt.Sprintf("writer already failed: %v", a.Err)
|
|
}
|
|
|
|
// Unwrap returns the error from the earlier failed write.
|
|
func (e Error) Unwrap() error {
|
|
return e.Err
|
|
}
|
|
|
|
// Is returns true if target is an Error.
|
|
func (e Error) Is(target error) bool {
|
|
_, ok := target.(Error)
|
|
return ok
|
|
}
|
|
|
|
type Writer struct {
|
|
err error
|
|
n int64
|
|
w io.Writer
|
|
}
|
|
|
|
func EnsureWriter(w io.Writer) *Writer {
|
|
scw, ok := w.(*Writer)
|
|
if !ok {
|
|
scw = NewWriter(w)
|
|
}
|
|
return scw
|
|
}
|
|
|
|
func NewWriter(w io.Writer) *Writer {
|
|
return &Writer{
|
|
w: w,
|
|
}
|
|
}
|
|
|
|
// Write attempts to write p to the underlying io.Writer if no earlier call to
|
|
// Write has failed. It returns the number of bytes written and an error if
|
|
// the write failed. If an earlier call did fail, no bytes will be written and
|
|
// err will be an Error containing the error from the failed call.
|
|
func (w *Writer) Write(p []byte) (n int, err error) {
|
|
if w.Failed() {
|
|
return 0, Error{Err: w.err}
|
|
}
|
|
n, err = w.w.Write(p)
|
|
w.n += int64(n)
|
|
if err != nil {
|
|
w.err = err
|
|
}
|
|
return n, err
|
|
}
|
|
|
|
// Status returns the total bytes written to the underlying writer,
|
|
// and any error resulting from a call to Write.
|
|
func (w *Writer) Status() (written int64, err error) {
|
|
return w.n, w.err
|
|
}
|
|
|
|
func (w *Writer) Failed() bool {
|
|
return w.err != nil
|
|
}
|
|
|
|
// ClearError makes this Writer forget any earlier error from Write, so that
|
|
// future calls to Write will attempt to write to the underlying io.Writer.
|
|
func (s *Writer) ClearError() {
|
|
s.err = nil
|
|
}
|