github.com/andybalholm/brotli@v1.0.6/reader.go (about)

     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 reading from 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  	if r.error_code < 0 {
    35  		// There was an unrecoverable error, leaving the Reader's state
    36  		// undefined. Clear out everything but the buffer.
    37  		*r = Reader{buf: r.buf}
    38  	}
    39  
    40  	decoderStateInit(r)
    41  	r.src = src
    42  	if r.buf == nil {
    43  		r.buf = make([]byte, readBufSize)
    44  	}
    45  	return nil
    46  }
    47  
    48  func (r *Reader) Read(p []byte) (n int, err error) {
    49  	if !decoderHasMoreOutput(r) && len(r.in) == 0 {
    50  		m, readErr := r.src.Read(r.buf)
    51  		if m == 0 {
    52  			// If readErr is `nil`, we just proxy underlying stream behavior.
    53  			return 0, readErr
    54  		}
    55  		r.in = r.buf[:m]
    56  	}
    57  
    58  	if len(p) == 0 {
    59  		return 0, nil
    60  	}
    61  
    62  	for {
    63  		var written uint
    64  		in_len := uint(len(r.in))
    65  		out_len := uint(len(p))
    66  		in_remaining := in_len
    67  		out_remaining := out_len
    68  		result := decoderDecompressStream(r, &in_remaining, &r.in, &out_remaining, &p)
    69  		written = out_len - out_remaining
    70  		n = int(written)
    71  
    72  		switch result {
    73  		case decoderResultSuccess:
    74  			if len(r.in) > 0 {
    75  				return n, errExcessiveInput
    76  			}
    77  			return n, nil
    78  		case decoderResultError:
    79  			return n, decodeError(decoderGetErrorCode(r))
    80  		case decoderResultNeedsMoreOutput:
    81  			if n == 0 {
    82  				return 0, io.ErrShortBuffer
    83  			}
    84  			return n, nil
    85  		case decoderNeedsMoreInput:
    86  		}
    87  
    88  		if len(r.in) != 0 {
    89  			return 0, errInvalidState
    90  		}
    91  
    92  		// Calling r.src.Read may block. Don't block if we have data to return.
    93  		if n > 0 {
    94  			return n, nil
    95  		}
    96  
    97  		// Top off the buffer.
    98  		encN, err := r.src.Read(r.buf)
    99  		if encN == 0 {
   100  			// Not enough data to complete decoding.
   101  			if err == io.EOF {
   102  				return 0, io.ErrUnexpectedEOF
   103  			}
   104  			return 0, err
   105  		}
   106  		r.in = r.buf[:encN]
   107  	}
   108  }