github.com/xraypb/xray-core@v1.6.6/common/buf/writer.go (about)

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