| // Copyright 2014 The Go Authors. |
| // See https://code.google.com/p/go/source/browse/CONTRIBUTORS |
| // Licensed under the same terms as Go itself: |
| // https://code.google.com/p/go/source/browse/LICENSE |
| |
| package http2 |
| |
| import ( |
| "errors" |
| ) |
| |
| // buffer is an io.ReadWriteCloser backed by a fixed size buffer. |
| // It never allocates, but moves old data as new data is written. |
| type buffer struct { |
| buf []byte |
| r, w int |
| closed bool |
| err error // err to return to reader |
| } |
| |
| var ( |
| errReadEmpty = errors.New("read from empty buffer") |
| errWriteFull = errors.New("write on full buffer") |
| ) |
| |
| // Read copies bytes from the buffer into p. |
| // It is an error to read when no data is available. |
| func (b *buffer) Read(p []byte) (n int, err error) { |
| n = copy(p, b.buf[b.r:b.w]) |
| b.r += n |
| if b.closed && b.r == b.w { |
| err = b.err |
| } else if b.r == b.w && n == 0 { |
| err = errReadEmpty |
| } |
| return n, err |
| } |
| |
| // Len returns the number of bytes of the unread portion of the buffer. |
| func (b *buffer) Len() int { |
| return b.w - b.r |
| } |
| |
| // Write copies bytes from p into the buffer. |
| // It is an error to write more data than the buffer can hold. |
| func (b *buffer) Write(p []byte) (n int, err error) { |
| if b.closed { |
| return 0, errors.New("closed") |
| } |
| |
| // Slide existing data to beginning. |
| if b.r > 0 && len(p) > len(b.buf)-b.w { |
| copy(b.buf, b.buf[b.r:b.w]) |
| b.w -= b.r |
| b.r = 0 |
| } |
| |
| // Write new data. |
| n = copy(b.buf[b.w:], p) |
| b.w += n |
| if n < len(p) { |
| err = errWriteFull |
| } |
| return n, err |
| } |
| |
| // Close marks the buffer as closed. Future calls to Write will |
| // return an error. Future calls to Read, once the buffer is |
| // empty, will return err. |
| func (b *buffer) Close(err error) { |
| if !b.closed { |
| b.closed = true |
| b.err = err |
| } |
| } |