package ctxio // // CopyN copies n bytes (or until an error) from src to dst. // // It returns the number of bytes copied and the earliest // // error encountered while copying. // // On return, written == n if and only if err == nil. // // // // If dst implements [ReaderFrom], the copy is implemented using it. // func CopyN(ctx context.Context, dst Writer, src Reader, n int64) (written int64, err error) { // written, err = Copy(ctx, dst, LimitReader(src, n)) // if written == n { // return n, nil // } // if written < n && err == nil { // // src stopped early; must have been EOF. // err = io.EOF // } // return // } // // Copy copies from src to dst until either EOF is reached // // on src or an error occurs. It returns the number of bytes // // copied and the first error encountered while copying, if any. // // // // A successful Copy returns err == nil, not err == EOF. // // Because Copy is defined to read from src until EOF, it does // // not treat an EOF from Read as an error to be reported. // // // // If src implements [WriterTo], // // the copy is implemented by calling src.WriteTo(dst). // // Otherwise, if dst implements [ReaderFrom], // // the copy is implemented by calling dst.ReadFrom(src). // func Copy(ctx context.Context, dst Writer, src Reader) (written int64, err error) { // return copyBuffer(ctx, dst, src, nil) // } // // copyBuffer is the actual implementation of Copy and CopyBuffer. // // if buf is nil, one is allocated. // func copyBuffer(ctx context.Context, dst Writer, src Reader, buf []byte) (written int64, err error) { // // If the reader has a WriteTo method, use it to do the copy. // // Avoids an allocation and a copy. // if wt, ok := src.(WriterTo); ok { // return wt.WriteTo(dst) // } // // Similarly, if the writer has a ReadFrom method, use it to do the copy. // if rt, ok := dst.(ReaderFrom); ok { // return rt.ReadFrom(src) // } // if buf == nil { // size := 32 * 1024 // if l, ok := src.(*LimitedReader); ok && int64(size) > l.N { // if l.N < 1 { // size = 1 // } else { // size = int(l.N) // } // } // buf = make([]byte, size) // } // for { // nr, er := src.Read(ctx, buf) // if nr > 0 { // nw, ew := dst.Write(ctx, buf[0:nr]) // if nw < 0 || nr < nw { // nw = 0 // if ew == nil { // ew = errInvalidWrite // } // } // written += int64(nw) // if ew != nil { // err = ew // break // } // if nr != nw { // err = io.ErrShortWrite // break // } // } // if er != nil { // if er != io.EOF { // err = er // } // break // } // } // return written, err // }