github.com/simonmittag/ws@v1.1.0-rc.5.0.20210419231947-82b846128245/wsflate/cbuf.go (about)

     1  package wsflate
     2  
     3  import (
     4  	"io"
     5  )
     6  
     7  // cbuf is a tiny proxy-buffer that writes all but 4 last bytes to the
     8  // destination.
     9  type cbuf struct {
    10  	buf [4]byte
    11  	n   int
    12  	dst io.Writer
    13  	err error
    14  }
    15  
    16  // Write implements io.Writer interface.
    17  func (c *cbuf) Write(p []byte) (int, error) {
    18  	if c.err != nil {
    19  		return 0, c.err
    20  	}
    21  	head, tail := c.split(p)
    22  	n := c.n + len(tail)
    23  	if n > len(c.buf) {
    24  		x := n - len(c.buf)
    25  		c.flush(c.buf[:x])
    26  		copy(c.buf[:], c.buf[x:])
    27  		c.n -= x
    28  	}
    29  	if len(head) > 0 {
    30  		c.flush(head)
    31  	}
    32  	copy(c.buf[c.n:], tail)
    33  	c.n = min(c.n+len(tail), len(c.buf))
    34  	return len(p), c.err
    35  }
    36  
    37  func (c *cbuf) flush(p []byte) {
    38  	if c.err == nil {
    39  		_, c.err = c.dst.Write(p)
    40  	}
    41  }
    42  
    43  func (c *cbuf) split(p []byte) (head, tail []byte) {
    44  	if n := len(p); n > len(c.buf) {
    45  		x := n - len(c.buf)
    46  		head = p[:x]
    47  		tail = p[x:]
    48  		return
    49  	}
    50  	return nil, p
    51  }
    52  
    53  func (c *cbuf) reset(dst io.Writer) {
    54  	c.n = 0
    55  	c.err = nil
    56  	c.buf = [4]byte{0, 0, 0, 0}
    57  	c.dst = dst
    58  }
    59  
    60  type suffixedReader struct {
    61  	r      io.Reader
    62  	pos    int // position in the suffix.
    63  	suffix [9]byte
    64  }
    65  
    66  func (r *suffixedReader) Read(p []byte) (n int, err error) {
    67  	if r.r != nil {
    68  		n, err = r.r.Read(p)
    69  		if err == io.EOF {
    70  			err = nil
    71  			r.r = nil
    72  		}
    73  		return n, err
    74  	}
    75  	if r.pos >= len(r.suffix) {
    76  		return 0, io.EOF
    77  	}
    78  	n = copy(p, r.suffix[r.pos:])
    79  	r.pos += n
    80  	return n, nil
    81  }
    82  
    83  func (r *suffixedReader) reset(src io.Reader) {
    84  	r.r = src
    85  	r.pos = 0
    86  }
    87  
    88  func min(a, b int) int {
    89  	if a < b {
    90  		return a
    91  	}
    92  	return b
    93  }