github.com/imannamdari/v2ray-core/v5@v5.0.5/common/buf/writer.go (about)

     1  package buf
     2  
     3  import (
     4  	"io"
     5  	"net"
     6  	"sync"
     7  
     8  	"github.com/imannamdari/v2ray-core/v5/common"
     9  	"github.com/imannamdari/v2ray-core/v5/common/errors"
    10  )
    11  
    12  // BufferToBytesWriter is a Writer that writes alloc.Buffer into underlying writer.
    13  type BufferToBytesWriter struct {
    14  	io.Writer
    15  
    16  	cache [][]byte
    17  }
    18  
    19  // WriteMultiBuffer implements Writer. This method takes ownership of the given buffer.
    20  func (w *BufferToBytesWriter) WriteMultiBuffer(mb MultiBuffer) error {
    21  	defer ReleaseMulti(mb)
    22  
    23  	size := mb.Len()
    24  	if size == 0 {
    25  		return nil
    26  	}
    27  
    28  	if len(mb) == 1 {
    29  		return WriteAllBytes(w.Writer, mb[0].Bytes())
    30  	}
    31  
    32  	if cap(w.cache) < len(mb) {
    33  		w.cache = make([][]byte, 0, len(mb))
    34  	}
    35  
    36  	bs := w.cache
    37  	for _, b := range mb {
    38  		bs = append(bs, b.Bytes())
    39  	}
    40  
    41  	defer func() {
    42  		for idx := range bs {
    43  			bs[idx] = nil
    44  		}
    45  	}()
    46  
    47  	nb := net.Buffers(bs)
    48  
    49  	for size > 0 {
    50  		n, err := nb.WriteTo(w.Writer)
    51  		if err != nil {
    52  			return err
    53  		}
    54  		size -= int32(n)
    55  	}
    56  
    57  	return nil
    58  }
    59  
    60  // ReadFrom implements io.ReaderFrom.
    61  func (w *BufferToBytesWriter) ReadFrom(reader io.Reader) (int64, error) {
    62  	var sc SizeCounter
    63  	err := Copy(NewReader(reader), w, CountSize(&sc))
    64  	return sc.Size, err
    65  }
    66  
    67  // BufferedWriter is a Writer with internal buffer.
    68  type BufferedWriter struct {
    69  	sync.Mutex
    70  	writer   Writer
    71  	buffer   *Buffer
    72  	buffered bool
    73  }
    74  
    75  // NewBufferedWriter creates a new BufferedWriter.
    76  func NewBufferedWriter(writer Writer) *BufferedWriter {
    77  	return &BufferedWriter{
    78  		writer:   writer,
    79  		buffer:   New(),
    80  		buffered: true,
    81  	}
    82  }
    83  
    84  // WriteByte implements io.ByteWriter.
    85  func (w *BufferedWriter) WriteByte(c byte) error {
    86  	return common.Error2(w.Write([]byte{c}))
    87  }
    88  
    89  // Write implements io.Writer.
    90  func (w *BufferedWriter) Write(b []byte) (int, error) {
    91  	if len(b) == 0 {
    92  		return 0, nil
    93  	}
    94  
    95  	w.Lock()
    96  	defer w.Unlock()
    97  
    98  	if !w.buffered {
    99  		if writer, ok := w.writer.(io.Writer); ok {
   100  			return writer.Write(b)
   101  		}
   102  	}
   103  
   104  	totalBytes := 0
   105  	for len(b) > 0 {
   106  		if w.buffer == nil {
   107  			w.buffer = New()
   108  		}
   109  
   110  		nBytes, err := w.buffer.Write(b)
   111  		totalBytes += nBytes
   112  		if err != nil {
   113  			return totalBytes, err
   114  		}
   115  		if !w.buffered || w.buffer.IsFull() {
   116  			if err := w.flushInternal(); err != nil {
   117  				return totalBytes, err
   118  			}
   119  		}
   120  		b = b[nBytes:]
   121  	}
   122  
   123  	return totalBytes, nil
   124  }
   125  
   126  // WriteMultiBuffer implements Writer. It takes ownership of the given MultiBuffer.
   127  func (w *BufferedWriter) WriteMultiBuffer(b MultiBuffer) error {
   128  	if b.IsEmpty() {
   129  		return nil
   130  	}
   131  
   132  	w.Lock()
   133  	defer w.Unlock()
   134  
   135  	if !w.buffered {
   136  		return w.writer.WriteMultiBuffer(b)
   137  	}
   138  
   139  	reader := MultiBufferContainer{
   140  		MultiBuffer: b,
   141  	}
   142  	defer reader.Close()
   143  
   144  	for !reader.MultiBuffer.IsEmpty() {
   145  		if w.buffer == nil {
   146  			w.buffer = New()
   147  		}
   148  		common.Must2(w.buffer.ReadFrom(&reader))
   149  		if w.buffer.IsFull() {
   150  			if err := w.flushInternal(); err != nil {
   151  				return err
   152  			}
   153  		}
   154  	}
   155  
   156  	return nil
   157  }
   158  
   159  // Flush flushes buffered content into underlying writer.
   160  func (w *BufferedWriter) Flush() error {
   161  	w.Lock()
   162  	defer w.Unlock()
   163  
   164  	return w.flushInternal()
   165  }
   166  
   167  func (w *BufferedWriter) flushInternal() error {
   168  	if w.buffer.IsEmpty() {
   169  		return nil
   170  	}
   171  
   172  	b := w.buffer
   173  	w.buffer = nil
   174  
   175  	if writer, ok := w.writer.(io.Writer); ok {
   176  		err := WriteAllBytes(writer, b.Bytes())
   177  		b.Release()
   178  		return err
   179  	}
   180  
   181  	return w.writer.WriteMultiBuffer(MultiBuffer{b})
   182  }
   183  
   184  // SetBuffered sets whether the internal buffer is used. If set to false, Flush() will be called to clear the buffer.
   185  func (w *BufferedWriter) SetBuffered(f bool) error {
   186  	w.Lock()
   187  	defer w.Unlock()
   188  
   189  	w.buffered = f
   190  	if !f {
   191  		return w.flushInternal()
   192  	}
   193  	return nil
   194  }
   195  
   196  // ReadFrom implements io.ReaderFrom.
   197  func (w *BufferedWriter) ReadFrom(reader io.Reader) (int64, error) {
   198  	if err := w.SetBuffered(false); err != nil {
   199  		return 0, err
   200  	}
   201  
   202  	var sc SizeCounter
   203  	err := Copy(NewReader(reader), w, CountSize(&sc))
   204  	return sc.Size, err
   205  }
   206  
   207  // Close implements io.Closable.
   208  func (w *BufferedWriter) Close() error {
   209  	if err := w.Flush(); err != nil {
   210  		return err
   211  	}
   212  	return common.Close(w.writer)
   213  }
   214  
   215  // SequentialWriter is a Writer that writes MultiBuffer sequentially into the underlying io.Writer.
   216  type SequentialWriter struct {
   217  	io.Writer
   218  }
   219  
   220  // WriteMultiBuffer implements Writer.
   221  func (w *SequentialWriter) WriteMultiBuffer(mb MultiBuffer) error {
   222  	mb, err := WriteMultiBuffer(w.Writer, mb)
   223  	ReleaseMulti(mb)
   224  	return err
   225  }
   226  
   227  type noOpWriter byte
   228  
   229  func (noOpWriter) WriteMultiBuffer(b MultiBuffer) error {
   230  	ReleaseMulti(b)
   231  	return nil
   232  }
   233  
   234  func (noOpWriter) Write(b []byte) (int, error) {
   235  	return len(b), nil
   236  }
   237  
   238  func (noOpWriter) ReadFrom(reader io.Reader) (int64, error) {
   239  	b := New()
   240  	defer b.Release()
   241  
   242  	totalBytes := int64(0)
   243  	for {
   244  		b.Clear()
   245  		_, err := b.ReadFrom(reader)
   246  		totalBytes += int64(b.Len())
   247  		if err != nil {
   248  			if errors.Cause(err) == io.EOF {
   249  				return totalBytes, nil
   250  			}
   251  			return totalBytes, err
   252  		}
   253  	}
   254  }
   255  
   256  var (
   257  	// Discard is a Writer that swallows all contents written in.
   258  	Discard Writer = noOpWriter(0)
   259  
   260  	// DiscardBytes is an io.Writer that swallows all contents written in.
   261  	DiscardBytes io.Writer = noOpWriter(0)
   262  )