github.com/xraypb/Xray-core@v1.8.1/common/buf/multi_buffer.go (about)

     1  package buf
     2  
     3  import (
     4  	"io"
     5  
     6  	"github.com/xraypb/Xray-core/common"
     7  	"github.com/xraypb/Xray-core/common/errors"
     8  	"github.com/xraypb/Xray-core/common/serial"
     9  )
    10  
    11  // ReadAllToBytes reads all content from the reader into a byte array, until EOF.
    12  func ReadAllToBytes(reader io.Reader) ([]byte, error) {
    13  	mb, err := ReadFrom(reader)
    14  	if err != nil {
    15  		return nil, err
    16  	}
    17  	if mb.Len() == 0 {
    18  		return nil, nil
    19  	}
    20  	b := make([]byte, mb.Len())
    21  	mb, _ = SplitBytes(mb, b)
    22  	ReleaseMulti(mb)
    23  	return b, nil
    24  }
    25  
    26  // MultiBuffer is a list of Buffers. The order of Buffer matters.
    27  type MultiBuffer []*Buffer
    28  
    29  // MergeMulti merges content from src to dest, and returns the new address of dest and src
    30  func MergeMulti(dest MultiBuffer, src MultiBuffer) (MultiBuffer, MultiBuffer) {
    31  	dest = append(dest, src...)
    32  	for idx := range src {
    33  		src[idx] = nil
    34  	}
    35  	return dest, src[:0]
    36  }
    37  
    38  // MergeBytes merges the given bytes into MultiBuffer and return the new address of the merged MultiBuffer.
    39  func MergeBytes(dest MultiBuffer, src []byte) MultiBuffer {
    40  	n := len(dest)
    41  	if n > 0 && !(dest)[n-1].IsFull() {
    42  		nBytes, _ := (dest)[n-1].Write(src)
    43  		src = src[nBytes:]
    44  	}
    45  
    46  	for len(src) > 0 {
    47  		b := New()
    48  		nBytes, _ := b.Write(src)
    49  		src = src[nBytes:]
    50  		dest = append(dest, b)
    51  	}
    52  
    53  	return dest
    54  }
    55  
    56  // ReleaseMulti releases all content of the MultiBuffer, and returns an empty MultiBuffer.
    57  func ReleaseMulti(mb MultiBuffer) MultiBuffer {
    58  	for i := range mb {
    59  		mb[i].Release()
    60  		mb[i] = nil
    61  	}
    62  	return mb[:0]
    63  }
    64  
    65  // Copy copied the beginning part of the MultiBuffer into the given byte array.
    66  func (mb MultiBuffer) Copy(b []byte) int {
    67  	total := 0
    68  	for _, bb := range mb {
    69  		nBytes := copy(b[total:], bb.Bytes())
    70  		total += nBytes
    71  		if int32(nBytes) < bb.Len() {
    72  			break
    73  		}
    74  	}
    75  	return total
    76  }
    77  
    78  // ReadFrom reads all content from reader until EOF.
    79  func ReadFrom(reader io.Reader) (MultiBuffer, error) {
    80  	mb := make(MultiBuffer, 0, 16)
    81  	for {
    82  		b := New()
    83  		_, err := b.ReadFullFrom(reader, Size)
    84  		if b.IsEmpty() {
    85  			b.Release()
    86  		} else {
    87  			mb = append(mb, b)
    88  		}
    89  		if err != nil {
    90  			if errors.Cause(err) == io.EOF || errors.Cause(err) == io.ErrUnexpectedEOF {
    91  				return mb, nil
    92  			}
    93  			return mb, err
    94  		}
    95  	}
    96  }
    97  
    98  // SplitBytes splits the given amount of bytes from the beginning of the MultiBuffer.
    99  // It returns the new address of MultiBuffer leftover, and number of bytes written into the input byte slice.
   100  func SplitBytes(mb MultiBuffer, b []byte) (MultiBuffer, int) {
   101  	totalBytes := 0
   102  	endIndex := -1
   103  	for i := range mb {
   104  		pBuffer := mb[i]
   105  		nBytes, _ := pBuffer.Read(b)
   106  		totalBytes += nBytes
   107  		b = b[nBytes:]
   108  		if !pBuffer.IsEmpty() {
   109  			endIndex = i
   110  			break
   111  		}
   112  		pBuffer.Release()
   113  		mb[i] = nil
   114  	}
   115  
   116  	if endIndex == -1 {
   117  		mb = mb[:0]
   118  	} else {
   119  		mb = mb[endIndex:]
   120  	}
   121  
   122  	return mb, totalBytes
   123  }
   124  
   125  // SplitFirstBytes splits the first buffer from MultiBuffer, and then copy its content into the given slice.
   126  func SplitFirstBytes(mb MultiBuffer, p []byte) (MultiBuffer, int) {
   127  	mb, b := SplitFirst(mb)
   128  	if b == nil {
   129  		return mb, 0
   130  	}
   131  	n := copy(p, b.Bytes())
   132  	b.Release()
   133  	return mb, n
   134  }
   135  
   136  // Compact returns another MultiBuffer by merging all content of the given one together.
   137  func Compact(mb MultiBuffer) MultiBuffer {
   138  	if len(mb) == 0 {
   139  		return mb
   140  	}
   141  
   142  	mb2 := make(MultiBuffer, 0, len(mb))
   143  	last := mb[0]
   144  
   145  	for i := 1; i < len(mb); i++ {
   146  		curr := mb[i]
   147  		if last.Len()+curr.Len() > Size {
   148  			mb2 = append(mb2, last)
   149  			last = curr
   150  		} else {
   151  			common.Must2(last.ReadFrom(curr))
   152  			curr.Release()
   153  		}
   154  	}
   155  
   156  	mb2 = append(mb2, last)
   157  	return mb2
   158  }
   159  
   160  // SplitFirst splits the first Buffer from the beginning of the MultiBuffer.
   161  func SplitFirst(mb MultiBuffer) (MultiBuffer, *Buffer) {
   162  	if len(mb) == 0 {
   163  		return mb, nil
   164  	}
   165  
   166  	b := mb[0]
   167  	mb[0] = nil
   168  	mb = mb[1:]
   169  	return mb, b
   170  }
   171  
   172  // SplitSize splits the beginning of the MultiBuffer into another one, for at most size bytes.
   173  func SplitSize(mb MultiBuffer, size int32) (MultiBuffer, MultiBuffer) {
   174  	if len(mb) == 0 {
   175  		return mb, nil
   176  	}
   177  
   178  	if mb[0].Len() > size {
   179  		b := New()
   180  		copy(b.Extend(size), mb[0].BytesTo(size))
   181  		mb[0].Advance(size)
   182  		return mb, MultiBuffer{b}
   183  	}
   184  
   185  	totalBytes := int32(0)
   186  	var r MultiBuffer
   187  	endIndex := -1
   188  	for i := range mb {
   189  		if totalBytes+mb[i].Len() > size {
   190  			endIndex = i
   191  			break
   192  		}
   193  		totalBytes += mb[i].Len()
   194  		r = append(r, mb[i])
   195  		mb[i] = nil
   196  	}
   197  	if endIndex == -1 {
   198  		// To reuse mb array
   199  		mb = mb[:0]
   200  	} else {
   201  		mb = mb[endIndex:]
   202  	}
   203  	return mb, r
   204  }
   205  
   206  // SplitMulti splits the beginning of the MultiBuffer into first one, the index i and after into second one
   207  func SplitMulti(mb MultiBuffer, i int) (MultiBuffer, MultiBuffer) {
   208  	mb2 := make(MultiBuffer, 0, len(mb))
   209  	if i < len(mb) && i >= 0 {
   210  		mb2 = append(mb2, mb[i:]...)
   211  		for j := i; j < len(mb); j++ {
   212  			mb[j] = nil
   213  		}
   214  		mb = mb[:i]
   215  	}
   216  	return mb, mb2
   217  }
   218  
   219  // WriteMultiBuffer writes all buffers from the MultiBuffer to the Writer one by one, and return error if any, with leftover MultiBuffer.
   220  func WriteMultiBuffer(writer io.Writer, mb MultiBuffer) (MultiBuffer, error) {
   221  	for {
   222  		mb2, b := SplitFirst(mb)
   223  		mb = mb2
   224  		if b == nil {
   225  			break
   226  		}
   227  
   228  		_, err := writer.Write(b.Bytes())
   229  		b.Release()
   230  		if err != nil {
   231  			return mb, err
   232  		}
   233  	}
   234  
   235  	return nil, nil
   236  }
   237  
   238  // Len returns the total number of bytes in the MultiBuffer.
   239  func (mb MultiBuffer) Len() int32 {
   240  	if mb == nil {
   241  		return 0
   242  	}
   243  
   244  	size := int32(0)
   245  	for _, b := range mb {
   246  		size += b.Len()
   247  	}
   248  	return size
   249  }
   250  
   251  // IsEmpty returns true if the MultiBuffer has no content.
   252  func (mb MultiBuffer) IsEmpty() bool {
   253  	for _, b := range mb {
   254  		if !b.IsEmpty() {
   255  			return false
   256  		}
   257  	}
   258  	return true
   259  }
   260  
   261  // String returns the content of the MultiBuffer in string.
   262  func (mb MultiBuffer) String() string {
   263  	v := make([]interface{}, len(mb))
   264  	for i, b := range mb {
   265  		v[i] = b
   266  	}
   267  	return serial.Concat(v...)
   268  }
   269  
   270  // MultiBufferContainer is a ReadWriteCloser wrapper over MultiBuffer.
   271  type MultiBufferContainer struct {
   272  	MultiBuffer
   273  }
   274  
   275  // Read implements io.Reader.
   276  func (c *MultiBufferContainer) Read(b []byte) (int, error) {
   277  	if c.MultiBuffer.IsEmpty() {
   278  		return 0, io.EOF
   279  	}
   280  
   281  	mb, nBytes := SplitBytes(c.MultiBuffer, b)
   282  	c.MultiBuffer = mb
   283  	return nBytes, nil
   284  }
   285  
   286  // ReadMultiBuffer implements Reader.
   287  func (c *MultiBufferContainer) ReadMultiBuffer() (MultiBuffer, error) {
   288  	mb := c.MultiBuffer
   289  	c.MultiBuffer = nil
   290  	return mb, nil
   291  }
   292  
   293  // Write implements io.Writer.
   294  func (c *MultiBufferContainer) Write(b []byte) (int, error) {
   295  	c.MultiBuffer = MergeBytes(c.MultiBuffer, b)
   296  	return len(b), nil
   297  }
   298  
   299  // WriteMultiBuffer implements Writer.
   300  func (c *MultiBufferContainer) WriteMultiBuffer(b MultiBuffer) error {
   301  	mb, _ := MergeMulti(c.MultiBuffer, b)
   302  	c.MultiBuffer = mb
   303  	return nil
   304  }
   305  
   306  // Close implements io.Closer.
   307  func (c *MultiBufferContainer) Close() error {
   308  	c.MultiBuffer = ReleaseMulti(c.MultiBuffer)
   309  	return nil
   310  }