github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/x/wasm/keeper/ioutil.go (about)

     1  package keeper
     2  
     3  import (
     4  	"bytes"
     5  	"compress/gzip"
     6  	"io"
     7  	"io/ioutil"
     8  
     9  	"github.com/fibonacci-chain/fbc/x/wasm/types"
    10  )
    11  
    12  // magic bytes to identify gzip.
    13  // See https://www.ietf.org/rfc/rfc1952.txt
    14  // and https://github.com/golang/go/blob/master/src/net/http/sniff.go#L186
    15  var gzipIdent = []byte("\x1F\x8B\x08")
    16  
    17  // uncompress returns gzip uncompressed content or given src when not gzip.
    18  func uncompress(src []byte, limit uint64) ([]byte, error) {
    19  	switch n := uint64(len(src)); {
    20  	case n < 3:
    21  		return src, nil
    22  	case n > limit:
    23  		return nil, types.ErrLimit
    24  	}
    25  	if !bytes.Equal(gzipIdent, src[0:3]) {
    26  		return src, nil
    27  	}
    28  	zr, err := gzip.NewReader(bytes.NewReader(src))
    29  	if err != nil {
    30  		return nil, err
    31  	}
    32  	zr.Multistream(false)
    33  	defer zr.Close()
    34  	return ioutil.ReadAll(LimitReader(zr, int64(limit)))
    35  }
    36  
    37  // LimitReader returns a Reader that reads from r
    38  // but stops with types.ErrLimit after n bytes.
    39  // The underlying implementation is a *io.LimitedReader.
    40  func LimitReader(r io.Reader, n int64) io.Reader {
    41  	return &LimitedReader{r: &io.LimitedReader{R: r, N: n}}
    42  }
    43  
    44  type LimitedReader struct {
    45  	r *io.LimitedReader
    46  }
    47  
    48  func (l *LimitedReader) Read(p []byte) (n int, err error) {
    49  	if l.r.N <= 0 {
    50  		return 0, types.ErrLimit
    51  	}
    52  	return l.r.Read(p)
    53  }