[145] | 1 | package brotli
|
---|
| 2 |
|
---|
| 3 | import (
|
---|
| 4 | "errors"
|
---|
| 5 | "io"
|
---|
| 6 | )
|
---|
| 7 |
|
---|
| 8 | type decodeError int
|
---|
| 9 |
|
---|
| 10 | func (err decodeError) Error() string {
|
---|
| 11 | return "brotli: " + string(decoderErrorString(int(err)))
|
---|
| 12 | }
|
---|
| 13 |
|
---|
| 14 | var errExcessiveInput = errors.New("brotli: excessive input")
|
---|
| 15 | var errInvalidState = errors.New("brotli: invalid state")
|
---|
| 16 |
|
---|
| 17 | // readBufSize is a "good" buffer size that avoids excessive round-trips
|
---|
| 18 | // between C and Go but doesn't waste too much memory on buffering.
|
---|
| 19 | // It is arbitrarily chosen to be equal to the constant used in io.Copy.
|
---|
| 20 | const readBufSize = 32 * 1024
|
---|
| 21 |
|
---|
| 22 | // NewReader creates a new Reader reading the given reader.
|
---|
| 23 | func NewReader(src io.Reader) *Reader {
|
---|
| 24 | r := new(Reader)
|
---|
| 25 | r.Reset(src)
|
---|
| 26 | return r
|
---|
| 27 | }
|
---|
| 28 |
|
---|
| 29 | // Reset discards the Reader's state and makes it equivalent to the result of
|
---|
| 30 | // its original state from NewReader, but writing to src instead.
|
---|
| 31 | // This permits reusing a Reader rather than allocating a new one.
|
---|
| 32 | // Error is always nil
|
---|
| 33 | func (r *Reader) Reset(src io.Reader) error {
|
---|
| 34 | decoderStateInit(r)
|
---|
| 35 | r.src = src
|
---|
| 36 | if r.buf == nil {
|
---|
| 37 | r.buf = make([]byte, readBufSize)
|
---|
| 38 | }
|
---|
| 39 | return nil
|
---|
| 40 | }
|
---|
| 41 |
|
---|
| 42 | func (r *Reader) Read(p []byte) (n int, err error) {
|
---|
| 43 | if !decoderHasMoreOutput(r) && len(r.in) == 0 {
|
---|
| 44 | m, readErr := r.src.Read(r.buf)
|
---|
| 45 | if m == 0 {
|
---|
| 46 | // If readErr is `nil`, we just proxy underlying stream behavior.
|
---|
| 47 | return 0, readErr
|
---|
| 48 | }
|
---|
| 49 | r.in = r.buf[:m]
|
---|
| 50 | }
|
---|
| 51 |
|
---|
| 52 | if len(p) == 0 {
|
---|
| 53 | return 0, nil
|
---|
| 54 | }
|
---|
| 55 |
|
---|
| 56 | for {
|
---|
| 57 | var written uint
|
---|
| 58 | in_len := uint(len(r.in))
|
---|
| 59 | out_len := uint(len(p))
|
---|
| 60 | in_remaining := in_len
|
---|
| 61 | out_remaining := out_len
|
---|
| 62 | result := decoderDecompressStream(r, &in_remaining, &r.in, &out_remaining, &p)
|
---|
| 63 | written = out_len - out_remaining
|
---|
| 64 | n = int(written)
|
---|
| 65 |
|
---|
| 66 | switch result {
|
---|
| 67 | case decoderResultSuccess:
|
---|
| 68 | if len(r.in) > 0 {
|
---|
| 69 | return n, errExcessiveInput
|
---|
| 70 | }
|
---|
| 71 | return n, nil
|
---|
| 72 | case decoderResultError:
|
---|
| 73 | return n, decodeError(decoderGetErrorCode(r))
|
---|
| 74 | case decoderResultNeedsMoreOutput:
|
---|
| 75 | if n == 0 {
|
---|
| 76 | return 0, io.ErrShortBuffer
|
---|
| 77 | }
|
---|
| 78 | return n, nil
|
---|
| 79 | case decoderNeedsMoreInput:
|
---|
| 80 | }
|
---|
| 81 |
|
---|
| 82 | if len(r.in) != 0 {
|
---|
| 83 | return 0, errInvalidState
|
---|
| 84 | }
|
---|
| 85 |
|
---|
| 86 | // Calling r.src.Read may block. Don't block if we have data to return.
|
---|
| 87 | if n > 0 {
|
---|
| 88 | return n, nil
|
---|
| 89 | }
|
---|
| 90 |
|
---|
| 91 | // Top off the buffer.
|
---|
| 92 | encN, err := r.src.Read(r.buf)
|
---|
| 93 | if encN == 0 {
|
---|
| 94 | // Not enough data to complete decoding.
|
---|
| 95 | if err == io.EOF {
|
---|
| 96 | return 0, io.ErrUnexpectedEOF
|
---|
| 97 | }
|
---|
| 98 | return 0, err
|
---|
| 99 | }
|
---|
| 100 | r.in = r.buf[:encN]
|
---|
| 101 | }
|
---|
| 102 | }
|
---|