github.com/erda-project/erda-infra@v1.0.10-0.20240327085753-f3a249292aeb/pkg/parallel-writer/buffer.go (about)

     1  // Copyright (c) 2021 Terminus, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package writer
    16  
    17  import (
    18  	"github.com/recallsong/go-utils/errorx"
    19  )
    20  
    21  // Buffer .
    22  type Buffer struct {
    23  	w       Writer
    24  	buf     []interface{}
    25  	maxSize int
    26  }
    27  
    28  // NewBuffer .
    29  func NewBuffer(w Writer, max int) *Buffer {
    30  	return &Buffer{
    31  		w:       w,
    32  		buf:     make([]interface{}, 0, max),
    33  		maxSize: max,
    34  	}
    35  }
    36  
    37  // Write .
    38  func (b *Buffer) Write(data interface{}) error {
    39  	if len(b.buf)+1 > b.maxSize {
    40  		err := b.Flush()
    41  		if err != nil {
    42  			return err
    43  		}
    44  	}
    45  	b.buf = append(b.buf, data)
    46  	return nil
    47  }
    48  
    49  // WriteN returns the number of buffers written to the data.
    50  // if a Flush error occurs, the error will be returned
    51  func (b *Buffer) WriteN(data ...interface{}) (int, error) {
    52  	alen := len(b.buf)
    53  	blen := len(data)
    54  	if alen+blen < b.maxSize {
    55  		b.buf = append(b.buf, data...)
    56  		return blen, nil
    57  	}
    58  	writes := 0
    59  	if alen >= b.maxSize {
    60  		// never reached
    61  		err := b.Flush()
    62  		if err != nil {
    63  			return 0, nil
    64  		}
    65  	} else if alen > 0 {
    66  		writes = b.maxSize - alen
    67  		b.buf = append(b.buf, data[0:writes]...)
    68  		err := b.Flush()
    69  		if err != nil {
    70  			return writes, err
    71  		}
    72  		data = data[writes:]
    73  		blen -= writes
    74  	}
    75  	for blen > b.maxSize {
    76  		b.buf = append(b.buf, data[0:b.maxSize]...)
    77  		writes += b.maxSize
    78  		err := b.Flush()
    79  		if err != nil {
    80  			return writes, err
    81  		}
    82  		data = data[b.maxSize:]
    83  		blen -= b.maxSize
    84  	}
    85  	if blen > 0 {
    86  		b.buf = append(b.buf, data...)
    87  		writes += blen
    88  	}
    89  	return writes, nil
    90  }
    91  
    92  // Flush .
    93  func (b *Buffer) Flush() error {
    94  	l := len(b.buf)
    95  	if l > 0 {
    96  		n, err := b.w.WriteN(b.buf...)
    97  		b.buf = b.buf[0 : l-n]
    98  		if err != nil {
    99  			return err
   100  		}
   101  	}
   102  	return nil
   103  }
   104  
   105  // Size .
   106  func (b *Buffer) Size() int {
   107  	return len(b.buf)
   108  }
   109  
   110  // Data .
   111  func (b *Buffer) Data() []interface{} {
   112  	return b.buf
   113  }
   114  
   115  // Close .
   116  func (b *Buffer) Close() error {
   117  	return errorx.NewMultiError(b.Flush(), b.w.Close()).MaybeUnwrap()
   118  }