import (
"errors"
+ "sync"
)
// Seek whence values.
// middle of reading a fixed-size block or data structure.
var ErrUnexpectedEOF = errors.New("unexpected EOF")
-// ErrNoProgress is returned by some clients of an io.Reader when
+// ErrNoProgress is returned by some clients of an Reader when
// many calls to Read have failed to return any data or error,
-// usually the sign of a broken io.Reader implementation.
+// usually the sign of a broken Reader implementation.
var ErrNoProgress = errors.New("multiple Read calls return no data or error")
// Reader is the interface that wraps the basic Read method.
//
// ReadFrom reads data from r until EOF or error.
// The return value n is the number of bytes read.
-// Any error except io.EOF encountered during the read is also returned.
+// Any error except EOF encountered during the read is also returned.
//
// The Copy function uses ReaderFrom if available.
type ReaderFrom interface {
// buf will not be used to perform the copy.
func CopyBuffer(dst Writer, src Reader, buf []byte) (written int64, err error) {
if buf != nil && len(buf) == 0 {
- panic("empty buffer in io.CopyBuffer")
+ panic("empty buffer in CopyBuffer")
}
return copyBuffer(dst, src, buf)
}
}
return
}
+
+// Discard is an Writer on which all Write calls succeed
+// without doing anything.
+var Discard Writer = discard{}
+
+type discard struct{}
+
+// discard implements ReaderFrom as an optimization so Copy to
+// ioutil.Discard can avoid doing unnecessary work.
+var _ ReaderFrom = discard{}
+
+func (discard) Write(p []byte) (int, error) {
+ return len(p), nil
+}
+
+func (discard) WriteString(s string) (int, error) {
+ return len(s), nil
+}
+
+var blackHolePool = sync.Pool{
+ New: func() interface{} {
+ b := make([]byte, 8192)
+ return &b
+ },
+}
+
+func (discard) ReadFrom(r Reader) (n int64, err error) {
+ bufp := blackHolePool.Get().(*[]byte)
+ readSize := 0
+ for {
+ readSize, err = r.Read(*bufp)
+ n += int64(readSize)
+ if err != nil {
+ blackHolePool.Put(bufp)
+ if err == EOF {
+ return n, nil
+ }
+ return
+ }
+ }
+}
+
+// NopCloser returns a ReadCloser with a no-op Close method wrapping
+// the provided Reader r.
+func NopCloser(r Reader) ReadCloser {
+ return nopCloser{r}
+}
+
+type nopCloser struct {
+ Reader
+}
+
+func (nopCloser) Close() error { return nil }
+
+// ReadAll reads from r until an error or EOF and returns the data it read.
+// A successful call returns err == nil, not err == EOF. Because ReadAll is
+// defined to read from src until EOF, it does not treat an EOF from Read
+// as an error to be reported.
+func ReadAll(r Reader) ([]byte, error) {
+ b := make([]byte, 0, 512)
+ for {
+ if len(b) == cap(b) {
+ // Add more capacity (let append pick how much).
+ b = append(b, 0)[:len(b)]
+ }
+ n, err := r.Read(b[len(b):cap(b)])
+ b = b[:len(b)+n]
+ if err != nil {
+ if err == EOF {
+ err = nil
+ }
+ return b, err
+ }
+ }
+}
package ioutil
import (
- "bytes"
"io"
"io/fs"
"os"
"sort"
- "sync"
)
-// readAll reads from r until an error or EOF and returns the data it read
-// from the internal buffer allocated with a specified capacity.
-func readAll(r io.Reader, capacity int64) (b []byte, err error) {
- var buf bytes.Buffer
- // If the buffer overflows, we will get bytes.ErrTooLarge.
- // Return that as an error. Any other panic remains.
- defer func() {
- e := recover()
- if e == nil {
- return
- }
- if panicErr, ok := e.(error); ok && panicErr == bytes.ErrTooLarge {
- err = panicErr
- } else {
- panic(e)
- }
- }()
- if int64(int(capacity)) == capacity {
- buf.Grow(int(capacity))
- }
- _, err = buf.ReadFrom(r)
- return buf.Bytes(), err
-}
-
// ReadAll reads from r until an error or EOF and returns the data it read.
// A successful call returns err == nil, not err == EOF. Because ReadAll is
// defined to read from src until EOF, it does not treat an EOF from Read
// as an error to be reported.
+//
+// As of Go 1.16, this function simply calls io.ReadAll.
func ReadAll(r io.Reader) ([]byte, error) {
- return readAll(r, bytes.MinRead)
+ return io.ReadAll(r)
}
// ReadFile reads the file named by filename and returns the contents.
defer f.Close()
// It's a good but not certain bet that FileInfo will tell us exactly how much to
// read, so let's try it but be prepared for the answer to be wrong.
- var n int64 = bytes.MinRead
+ const minRead = 512
+ var n int64 = minRead
if fi, err := f.Stat(); err == nil {
// As initial capacity for readAll, use Size + a little extra in case Size
// cheaply. If the size was wrong, we'll either waste some space off the end
// or reallocate as needed, but in the overwhelmingly common case we'll get
// it just right.
- if size := fi.Size() + bytes.MinRead; size > n {
+ if size := fi.Size() + minRead; size > n {
n = size
}
}
- return readAll(f, n)
+
+ if int64(int(n)) != n {
+ n = minRead
+ }
+
+ b := make([]byte, 0, n)
+ for {
+ if len(b) == cap(b) {
+ // Add more capacity (let append pick how much).
+ b = append(b, 0)[:len(b)]
+ }
+ n, err := f.Read(b[len(b):cap(b)])
+ b = b[:len(b)+n]
+ if err != nil {
+ if err == io.EOF {
+ err = nil
+ }
+ return b, err
+ }
+ }
}
// WriteFile writes data to a file named by filename.
return list, nil
}
-type nopCloser struct {
- io.Reader
-}
-
-func (nopCloser) Close() error { return nil }
-
// NopCloser returns a ReadCloser with a no-op Close method wrapping
// the provided Reader r.
+//
+// As of Go 1.16, this function simply calls io.NopCloser.
func NopCloser(r io.Reader) io.ReadCloser {
- return nopCloser{r}
-}
-
-type devNull int
-
-// devNull implements ReaderFrom as an optimization so io.Copy to
-// ioutil.Discard can avoid doing unnecessary work.
-var _ io.ReaderFrom = devNull(0)
-
-func (devNull) Write(p []byte) (int, error) {
- return len(p), nil
-}
-
-func (devNull) WriteString(s string) (int, error) {
- return len(s), nil
-}
-
-var blackHolePool = sync.Pool{
- New: func() interface{} {
- b := make([]byte, 8192)
- return &b
- },
-}
-
-func (devNull) ReadFrom(r io.Reader) (n int64, err error) {
- bufp := blackHolePool.Get().(*[]byte)
- readSize := 0
- for {
- readSize, err = r.Read(*bufp)
- n += int64(readSize)
- if err != nil {
- blackHolePool.Put(bufp)
- if err == io.EOF {
- return n, nil
- }
- return
- }
- }
+ return io.NopCloser(r)
}
// Discard is an io.Writer on which all Write calls succeed
// without doing anything.
-var Discard io.Writer = devNull(0)
+//
+// As of Go 1.16, this value is simply io.Discard.
+var Discard io.Writer = io.Discard