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 }