Add ReadFrom and WriteTo methods to bytes.Buffer, to enable i/o without buffer allocation.
Use them in Copy and Copyn.
Speed up ReadFile by using ReadFrom and avoiding Copy altogether (a minor win).
R=rsc, gri
CC=golang-dev
https://golang.org/cl/166041
diff --git a/src/pkg/io/io.go b/src/pkg/io/io.go
index c4850da..68c5ccc 100644
--- a/src/pkg/io/io.go
+++ b/src/pkg/io/io.go
@@ -112,6 +112,16 @@
Seeker;
}
+// ReaderFrom is the interface that wraps the ReadFrom method.
+type ReaderFrom interface {
+ ReadFrom(r Reader) (n int64, err os.Error);
+}
+
+// WriterTo is the interface that wraps the WriteTo method.
+type WriterTo interface {
+ WriteTo(w Writer) (n int64, err os.Error);
+}
+
// ReaderAt is the interface that wraps the basic ReadAt method.
//
// ReadAt reads len(p) bytes into p starting at offset off in the
@@ -178,7 +188,15 @@
// Copyn copies n bytes (or until an error) from src to dst.
// It returns the number of bytes copied and the error, if any.
+//
+// If dst implements the ReaderFrom interface,
+// the copy is implemented by calling dst.ReadFrom(src).
func Copyn(dst Writer, src Reader, n int64) (written int64, err os.Error) {
+ // If the writer has a ReadFrom method, use it to to do the copy.
+ // Avoids a buffer allocation and a copy.
+ if rt, ok := dst.(ReaderFrom); ok {
+ return rt.ReadFrom(LimitReader(src, n))
+ }
buf := make([]byte, 32*1024);
for written < n {
l := len(buf);
@@ -211,7 +229,21 @@
// 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 error, if any.
+//
+// If dst implements the ReaderFrom interface,
+// the copy is implemented by calling dst.ReadFrom(src).
+// Otherwise, if src implements the WriterTo interface,
+// the copy is implemented by calling src.WriteTo(dst).
func Copy(dst Writer, src Reader) (written int64, err os.Error) {
+ // If the writer has a ReadFrom method, use it to to do the copy.
+ // Avoids an allocation and a copy.
+ if rt, ok := dst.(ReaderFrom); ok {
+ return rt.ReadFrom(src)
+ }
+ // Similarly, if the reader has a WriteTo method, use it to to do the copy.
+ if wt, ok := src.(WriterTo); ok {
+ return wt.WriteTo(dst)
+ }
buf := make([]byte, 32*1024);
for {
nr, er := src.Read(buf);