forked from TrueCloudLab/distribution
77 lines
1.7 KiB
Go
77 lines
1.7 KiB
Go
|
// 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")
|
||
|
errWriteClosed = errors.New("write on closed 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, errWriteClosed
|
||
|
}
|
||
|
|
||
|
// 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
|
||
|
}
|
||
|
}
|