github.com/weedge/lib@v0.0.0-20230424045628-a36dcc1d90e4/poller/buffer.go (about)

     1  package poller
     2  
     3  import (
     4  	"io"
     5  	"syscall"
     6  )
     7  
     8  // Buffer Read buffer, one read buffer for each tcp long connection
     9  type Buffer struct {
    10  	// todo: use bytes.Buffer ->  buffer pool
    11  	// buff   bytes.Buffer
    12  	buf   []byte // In-application cache
    13  	start int    // The start position of a valid byte
    14  	end   int    // End position of a valid byte
    15  }
    16  
    17  // NewBuffer Creates a buffer
    18  func NewBuffer(bytes []byte) *Buffer {
    19  	return &Buffer{buf: bytes, start: 0, end: 0}
    20  }
    21  
    22  func (b *Buffer) Len() int {
    23  	return b.end - b.start
    24  }
    25  
    26  // reset Reset cache (moves useful bytes forward)
    27  func (b *Buffer) reset() {
    28  	if b.start == 0 {
    29  		return
    30  	}
    31  	end := b.end
    32  	if b.end > len(b.buf) {
    33  		end = len(b.buf)
    34  	}
    35  	copy(b.buf, b.buf[b.start:end])
    36  	end -= b.start
    37  	b.start = 0
    38  	b.end = end
    39  }
    40  
    41  // ReadFromFD reads data from the file descriptor
    42  func (b *Buffer) ReadFromFD(fd int) error {
    43  	b.reset()
    44  	n, err := syscall.Read(fd, b.buf[b.end:])
    45  	if err != nil {
    46  		return err
    47  	}
    48  	if n == 0 {
    49  		return syscall.EAGAIN
    50  	}
    51  	b.end += n
    52  	return nil
    53  }
    54  
    55  // AsyncReadFromFD
    56  // async block read event from fd to buf
    57  func (b *Buffer) AsyncReadFromFD(fd int, uring *ioUring, cb EventCallBack) error {
    58  	b.reset()
    59  	uring.addRecvSqe(func(info *eventInfo) error {
    60  		n := info.cqe.Res
    61  		if n < 0 {
    62  			return ErrIOUringReadFail
    63  		}
    64  		if n == 0 {
    65  			return syscall.EAGAIN
    66  		}
    67  		b.end += int(n)
    68  		//log.Infof("cb %+v buff start %d end %d n %d buff %s", cb, b.start, b.end, n, b.buf[b.start:b.end])
    69  		err := cb(info)
    70  		return err
    71  	}, fd, b.buf[b.end:], len(b.buf[b.end:]), 0)
    72  
    73  	return nil
    74  }
    75  
    76  // ReadFromReader reads data from the reader. If the reader blocks, it will block
    77  func (b *Buffer) ReadFromReader(reader io.Reader) (int, error) {
    78  	b.reset()
    79  	n, err := reader.Read(b.buf[b.end:])
    80  	if err != nil {
    81  		return n, err
    82  	}
    83  	b.end += n
    84  	return n, nil
    85  }
    86  
    87  // Seek returns n bytes without a shift, or an error if there are not enough bytes
    88  func (b *Buffer) Seek(len int) ([]byte, error) {
    89  	if b.end-b.start >= len {
    90  		buf := b.buf[b.start : b.start+len]
    91  		return buf, nil
    92  	}
    93  	return nil, ErrBufferNotEnough
    94  }
    95  
    96  // Read Discard offset fields and read n fields. If there are not enough bytes, an error is returned
    97  func (b *Buffer) Read(offset, limit int) ([]byte, error) {
    98  	if b.Len() < offset+limit {
    99  		return nil, ErrBufferNotEnough
   100  	}
   101  	b.start += offset
   102  	buf := b.buf[b.start : b.start+limit]
   103  	b.start += limit
   104  	return buf, nil
   105  }
   106  
   107  // ReadAll Reads all bytes
   108  func (b *Buffer) ReadAll() []byte {
   109  	buf, _ := b.Read(b.start, b.end)
   110  	return buf
   111  }