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 | }
|
---|