@@ -8,6 +8,7 @@ package net
88
99import (
1010 "errors"
11+ "io"
1112 "time"
1213)
1314
@@ -318,3 +319,77 @@ var errClosed = errNetClosing{}
318319// in another error, and should normally be tested using
319320// errors.Is(err, net.ErrClosed).
320321var ErrClosed error = errClosed
322+
323+ // buffersWriter is the interface implemented by Conns that support a
324+ // "writev"-like batch write optimization.
325+ // writeBuffers should fully consume and write all chunks from the
326+ // provided Buffers, else it should report a non-nil error.
327+ type buffersWriter interface {
328+ writeBuffers (* Buffers ) (int64 , error )
329+ }
330+
331+ // Buffers contains zero or more runs of bytes to write.
332+ //
333+ // On certain machines, for certain types of connections, this is
334+ // optimized into an OS-specific batch write operation (such as
335+ // "writev").
336+ type Buffers [][]byte
337+
338+ var (
339+ _ io.WriterTo = (* Buffers )(nil )
340+ _ io.Reader = (* Buffers )(nil )
341+ )
342+
343+ // WriteTo writes contents of the buffers to w.
344+ //
345+ // WriteTo implements [io.WriterTo] for [Buffers].
346+ //
347+ // WriteTo modifies the slice v as well as v[i] for 0 <= i < len(v),
348+ // but does not modify v[i][j] for any i, j.
349+ func (v * Buffers ) WriteTo (w io.Writer ) (n int64 , err error ) {
350+ if wv , ok := w .(buffersWriter ); ok {
351+ return wv .writeBuffers (v )
352+ }
353+ for _ , b := range * v {
354+ nb , err := w .Write (b )
355+ n += int64 (nb )
356+ if err != nil {
357+ v .consume (n )
358+ return n , err
359+ }
360+ }
361+ v .consume (n )
362+ return n , nil
363+ }
364+
365+ // Read from the buffers.
366+ //
367+ // Read implements [io.Reader] for [Buffers].
368+ //
369+ // Read modifies the slice v as well as v[i] for 0 <= i < len(v),
370+ // but does not modify v[i][j] for any i, j.
371+ func (v * Buffers ) Read (p []byte ) (n int , err error ) {
372+ for len (p ) > 0 && len (* v ) > 0 {
373+ n0 := copy (p , (* v )[0 ])
374+ v .consume (int64 (n0 ))
375+ p = p [n0 :]
376+ n += n0
377+ }
378+ if len (* v ) == 0 {
379+ err = io .EOF
380+ }
381+ return
382+ }
383+
384+ func (v * Buffers ) consume (n int64 ) {
385+ for len (* v ) > 0 {
386+ ln0 := int64 (len ((* v )[0 ]))
387+ if ln0 > n {
388+ (* v )[0 ] = (* v )[0 ][n :]
389+ return
390+ }
391+ n -= ln0
392+ (* v )[0 ] = nil
393+ * v = (* v )[1 :]
394+ }
395+ }
0 commit comments