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 }