github.com/cloudwego/kitex@v0.9.0/pkg/remote/trans/netpoll/bytebuf.go (about)

     1  /*
     2   * Copyright 2021 CloudWeGo Authors
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package netpoll
    18  
    19  import (
    20  	"errors"
    21  	"io"
    22  	"sync"
    23  
    24  	"github.com/cloudwego/netpoll"
    25  
    26  	"github.com/cloudwego/kitex/pkg/remote"
    27  )
    28  
    29  var bytebufPool sync.Pool
    30  
    31  func init() {
    32  	bytebufPool.New = newNetpollByteBuffer
    33  }
    34  
    35  // NewReaderByteBuffer creates a new remote.ByteBuffer using the given netpoll.ZeroCopyReader.
    36  func NewReaderByteBuffer(r netpoll.Reader) remote.ByteBuffer {
    37  	bytebuf := bytebufPool.Get().(*netpollByteBuffer)
    38  	bytebuf.reader = r
    39  	// TODO(wangtieju): fix me when netpoll support netpoll.Reader
    40  	// and LinkBuffer not support io.Reader, type assertion would fail when r is from NewBuffer
    41  	if ir, ok := r.(io.Reader); ok {
    42  		bytebuf.ioReader = ir
    43  	}
    44  	bytebuf.status = remote.BitReadable
    45  	bytebuf.readSize = 0
    46  	return bytebuf
    47  }
    48  
    49  // NewWriterByteBuffer creates a new remote.ByteBuffer using the given netpoll.ZeroCopyWriter.
    50  func NewWriterByteBuffer(w netpoll.Writer) remote.ByteBuffer {
    51  	bytebuf := bytebufPool.Get().(*netpollByteBuffer)
    52  	bytebuf.writer = w
    53  	// TODO(wangtieju): fix me when netpoll support netpoll.Writer
    54  	// and LinkBuffer not support io.Reader, type assertion would fail when w is from NewBuffer
    55  	if iw, ok := w.(io.Writer); ok {
    56  		bytebuf.ioWriter = iw
    57  	}
    58  	bytebuf.status = remote.BitWritable
    59  	return bytebuf
    60  }
    61  
    62  // NewReaderWriterByteBuffer creates a new remote.ByteBuffer using the given netpoll.ZeroCopyReadWriter.
    63  func NewReaderWriterByteBuffer(rw netpoll.ReadWriter) remote.ByteBuffer {
    64  	bytebuf := bytebufPool.Get().(*netpollByteBuffer)
    65  	bytebuf.writer = rw
    66  	bytebuf.reader = rw
    67  	// TODO(wangtieju): fix me when netpoll support netpoll.ReadWriter
    68  	// and LinkBuffer not support io.ReadWriter, type assertion would fail when rw is from NewBuffer
    69  	if irw, ok := rw.(io.ReadWriter); ok {
    70  		bytebuf.ioReader = irw
    71  		bytebuf.ioWriter = irw
    72  	}
    73  	bytebuf.status = remote.BitWritable | remote.BitReadable
    74  	return bytebuf
    75  }
    76  
    77  func newNetpollByteBuffer() interface{} {
    78  	return &netpollByteBuffer{}
    79  }
    80  
    81  type netpollByteBuffer struct {
    82  	writer   netpoll.Writer
    83  	reader   netpoll.Reader
    84  	ioReader io.Reader
    85  	ioWriter io.Writer
    86  	status   int
    87  	readSize int
    88  }
    89  
    90  var _ remote.ByteBuffer = &netpollByteBuffer{}
    91  
    92  // Next reads n bytes sequentially, returns the original address.
    93  func (b *netpollByteBuffer) Next(n int) (p []byte, err error) {
    94  	if b.status&remote.BitReadable == 0 {
    95  		return nil, errors.New("unreadable buffer, cannot support Next")
    96  	}
    97  	if p, err = b.reader.Next(n); err == nil {
    98  		b.readSize += n
    99  	}
   100  	return
   101  }
   102  
   103  // Peek returns the next n bytes without advancing the reader.
   104  func (b *netpollByteBuffer) Peek(n int) (buf []byte, err error) {
   105  	if b.status&remote.BitReadable == 0 {
   106  		return nil, errors.New("unreadable buffer, cannot support Peek")
   107  	}
   108  	return b.reader.Peek(n)
   109  }
   110  
   111  // Skip is used to skip n bytes, it's much faster than Next.
   112  // Skip will not cause release.
   113  func (b *netpollByteBuffer) Skip(n int) (err error) {
   114  	if b.status&remote.BitReadable == 0 {
   115  		return errors.New("unreadable buffer, cannot support Skip")
   116  	}
   117  	return b.reader.Skip(n)
   118  }
   119  
   120  // ReadableLen returns the total length of readable buffer.
   121  func (b *netpollByteBuffer) ReadableLen() (n int) {
   122  	if b.status&remote.BitReadable == 0 {
   123  		return -1
   124  	}
   125  	return b.reader.Len()
   126  }
   127  
   128  // Read implement io.Reader
   129  func (b *netpollByteBuffer) Read(p []byte) (n int, err error) {
   130  	if b.status&remote.BitReadable == 0 {
   131  		return -1, errors.New("unreadable buffer, cannot support Read")
   132  	}
   133  	if b.ioReader != nil {
   134  		return b.ioReader.Read(p)
   135  	}
   136  	return -1, errors.New("ioReader is nil")
   137  }
   138  
   139  // ReadString is a more efficient way to read string than Next.
   140  func (b *netpollByteBuffer) ReadString(n int) (s string, err error) {
   141  	if b.status&remote.BitReadable == 0 {
   142  		return "", errors.New("unreadable buffer, cannot support ReadString")
   143  	}
   144  	if s, err = b.reader.ReadString(n); err == nil {
   145  		b.readSize += n
   146  	}
   147  	return
   148  }
   149  
   150  // ReadBinary like ReadString.
   151  // Returns a copy of original buffer.
   152  func (b *netpollByteBuffer) ReadBinary(n int) (p []byte, err error) {
   153  	if b.status&remote.BitReadable == 0 {
   154  		return p, errors.New("unreadable buffer, cannot support ReadBinary")
   155  	}
   156  	if p, err = b.reader.ReadBinary(n); err == nil {
   157  		b.readSize += n
   158  	}
   159  	return
   160  }
   161  
   162  // Malloc n bytes sequentially in the writer buffer.
   163  func (b *netpollByteBuffer) Malloc(n int) (buf []byte, err error) {
   164  	if b.status&remote.BitWritable == 0 {
   165  		return nil, errors.New("unwritable buffer, cannot support Malloc")
   166  	}
   167  	return b.writer.Malloc(n)
   168  }
   169  
   170  // MallocLen returns the total length of the buffer malloced.
   171  func (b *netpollByteBuffer) MallocLen() (length int) {
   172  	if b.status&remote.BitWritable == 0 {
   173  		return -1
   174  	}
   175  	return b.writer.MallocLen()
   176  }
   177  
   178  // Write implement io.Writer
   179  func (b *netpollByteBuffer) Write(p []byte) (n int, err error) {
   180  	if b.status&remote.BitWritable == 0 {
   181  		return -1, errors.New("unwritable buffer, cannot support Write")
   182  	}
   183  	if b.ioWriter != nil {
   184  		return b.ioWriter.Write(p)
   185  	}
   186  	return -1, errors.New("ioWriter is nil")
   187  }
   188  
   189  // WriteString is a more efficient way to write string, using the unsafe method to convert the string to []byte.
   190  func (b *netpollByteBuffer) WriteString(s string) (n int, err error) {
   191  	if b.status&remote.BitWritable == 0 {
   192  		return -1, errors.New("unwritable buffer, cannot support WriteString")
   193  	}
   194  	return b.writer.WriteString(s)
   195  }
   196  
   197  // WriteBinary writes the []byte directly. Callers must guarantee that the []byte doesn't change.
   198  func (b *netpollByteBuffer) WriteBinary(p []byte) (n int, err error) {
   199  	if b.status&remote.BitWritable == 0 {
   200  		return -1, errors.New("unwritable buffer, cannot support WriteBinary")
   201  	}
   202  	return b.writer.WriteBinary(p)
   203  }
   204  
   205  // WriteDirect is a way to write []byte without copying, and splits the original buffer.
   206  func (b *netpollByteBuffer) WriteDirect(p []byte, remainCap int) error {
   207  	if b.status&remote.BitWritable == 0 {
   208  		return errors.New("unwritable buffer, cannot support WriteBinary")
   209  	}
   210  	return b.writer.WriteDirect(p, remainCap)
   211  }
   212  
   213  // ReadLen returns the size already read.
   214  func (b *netpollByteBuffer) ReadLen() (n int) {
   215  	return b.readSize
   216  }
   217  
   218  // Flush writes any malloc data to the underlying io.Writer.
   219  // The malloced buffer must be set correctly.
   220  func (b *netpollByteBuffer) Flush() (err error) {
   221  	if b.status&remote.BitWritable == 0 {
   222  		return errors.New("unwritable buffer, cannot support Flush")
   223  	}
   224  	return b.writer.Flush()
   225  }
   226  
   227  // NewBuffer returns a new writable remote.ByteBuffer.
   228  func (b *netpollByteBuffer) NewBuffer() remote.ByteBuffer {
   229  	return NewWriterByteBuffer(netpoll.NewLinkBuffer())
   230  }
   231  
   232  // AppendBuffer appends buf to the original buffer.
   233  func (b *netpollByteBuffer) AppendBuffer(buf remote.ByteBuffer) (err error) {
   234  	subBuf := buf.(*netpollByteBuffer)
   235  	err = b.writer.Append(subBuf.writer)
   236  	buf.Release(nil)
   237  	return
   238  }
   239  
   240  // Bytes are not supported in netpoll bytebuf.
   241  func (b *netpollByteBuffer) Bytes() (buf []byte, err error) {
   242  	return nil, errors.New("method Bytes() not support in netpoll bytebuf")
   243  }
   244  
   245  // Release will free the buffer already read.
   246  // After release, buffer read by Next/Skip/Peek is invalid.
   247  func (b *netpollByteBuffer) Release(e error) (err error) {
   248  	if b.reader != nil {
   249  		// 重复执行Release nil panic
   250  		err = b.reader.Release()
   251  	}
   252  	b.zero()
   253  	bytebufPool.Put(b)
   254  	return
   255  }
   256  
   257  func (b *netpollByteBuffer) zero() {
   258  	b.writer = nil
   259  	b.reader = nil
   260  	b.ioReader = nil
   261  	b.ioWriter = nil
   262  	b.status = 0
   263  	b.readSize = 0
   264  }