github.com/eagleql/xray-core@v1.4.4/common/buf/multi_buffer.go (about)

     1  package buf
     2  
     3  import (
     4  	"io"
     5  
     6  	"github.com/eagleql/xray-core/common"
     7  	"github.com/eagleql/xray-core/common/errors"
     8  	"github.com/eagleql/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 release 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  // WriteMultiBuffer writes all buffers from the MultiBuffer to the Writer one by one, and return error if any, with leftover MultiBuffer.
   207  func WriteMultiBuffer(writer io.Writer, mb MultiBuffer) (MultiBuffer, error) {
   208  	for {
   209  		mb2, b := SplitFirst(mb)
   210  		mb = mb2
   211  		if b == nil {
   212  			break
   213  		}
   214  
   215  		_, err := writer.Write(b.Bytes())
   216  		b.Release()
   217  		if err != nil {
   218  			return mb, err
   219  		}
   220  	}
   221  
   222  	return nil, nil
   223  }
   224  
   225  // Len returns the total number of bytes in the MultiBuffer.
   226  func (mb MultiBuffer) Len() int32 {
   227  	if mb == nil {
   228  		return 0
   229  	}
   230  
   231  	size := int32(0)
   232  	for _, b := range mb {
   233  		size += b.Len()
   234  	}
   235  	return size
   236  }
   237  
   238  // IsEmpty return true if the MultiBuffer has no content.
   239  func (mb MultiBuffer) IsEmpty() bool {
   240  	for _, b := range mb {
   241  		if !b.IsEmpty() {
   242  			return false
   243  		}
   244  	}
   245  	return true
   246  }
   247  
   248  // String returns the content of the MultiBuffer in string.
   249  func (mb MultiBuffer) String() string {
   250  	v := make([]interface{}, len(mb))
   251  	for i, b := range mb {
   252  		v[i] = b
   253  	}
   254  	return serial.Concat(v...)
   255  }
   256  
   257  // MultiBufferContainer is a ReadWriteCloser wrapper over MultiBuffer.
   258  type MultiBufferContainer struct {
   259  	MultiBuffer
   260  }
   261  
   262  // Read implements io.Reader.
   263  func (c *MultiBufferContainer) Read(b []byte) (int, error) {
   264  	if c.MultiBuffer.IsEmpty() {
   265  		return 0, io.EOF
   266  	}
   267  
   268  	mb, nBytes := SplitBytes(c.MultiBuffer, b)
   269  	c.MultiBuffer = mb
   270  	return nBytes, nil
   271  }
   272  
   273  // ReadMultiBuffer implements Reader.
   274  func (c *MultiBufferContainer) ReadMultiBuffer() (MultiBuffer, error) {
   275  	mb := c.MultiBuffer
   276  	c.MultiBuffer = nil
   277  	return mb, nil
   278  }
   279  
   280  // Write implements io.Writer.
   281  func (c *MultiBufferContainer) Write(b []byte) (int, error) {
   282  	c.MultiBuffer = MergeBytes(c.MultiBuffer, b)
   283  	return len(b), nil
   284  }
   285  
   286  // WriteMultiBuffer implement Writer.
   287  func (c *MultiBufferContainer) WriteMultiBuffer(b MultiBuffer) error {
   288  	mb, _ := MergeMulti(c.MultiBuffer, b)
   289  	c.MultiBuffer = mb
   290  	return nil
   291  }
   292  
   293  // Close implement io.Closer.
   294  func (c *MultiBufferContainer) Close() error {
   295  	c.MultiBuffer = ReleaseMulti(c.MultiBuffer)
   296  	return nil
   297  }