replace zxq.co/ripple/hanayo
This commit is contained in:
		
							
								
								
									
										37
									
								
								vendor/github.com/klauspost/compress/zlib/example_test.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								vendor/github.com/klauspost/compress/zlib/example_test.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,37 @@
 | 
			
		||||
// Copyright 2012 The Go Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a BSD-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
package zlib_test
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"compress/zlib"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"os"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func ExampleNewWriter() {
 | 
			
		||||
	var b bytes.Buffer
 | 
			
		||||
 | 
			
		||||
	w := zlib.NewWriter(&b)
 | 
			
		||||
	w.Write([]byte("hello, world\n"))
 | 
			
		||||
	w.Close()
 | 
			
		||||
	fmt.Println(b.Bytes())
 | 
			
		||||
	// Output: [120 156 202 72 205 201 201 215 81 40 207 47 202 73 225 2 4 0 0 255 255 33 231 4 147]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func ExampleNewReader() {
 | 
			
		||||
	buff := []byte{120, 156, 202, 72, 205, 201, 201, 215, 81, 40, 207,
 | 
			
		||||
		47, 202, 73, 225, 2, 4, 0, 0, 255, 255, 33, 231, 4, 147}
 | 
			
		||||
	b := bytes.NewReader(buff)
 | 
			
		||||
 | 
			
		||||
	r, err := zlib.NewReader(b)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic(err)
 | 
			
		||||
	}
 | 
			
		||||
	io.Copy(os.Stdout, r)
 | 
			
		||||
	// Output: hello, world
 | 
			
		||||
	r.Close()
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										178
									
								
								vendor/github.com/klauspost/compress/zlib/reader.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										178
									
								
								vendor/github.com/klauspost/compress/zlib/reader.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,178 @@
 | 
			
		||||
// Copyright 2009 The Go Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a BSD-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
Package zlib implements reading and writing of zlib format compressed data,
 | 
			
		||||
as specified in RFC 1950.
 | 
			
		||||
 | 
			
		||||
The implementation provides filters that uncompress during reading
 | 
			
		||||
and compress during writing.  For example, to write compressed data
 | 
			
		||||
to a buffer:
 | 
			
		||||
 | 
			
		||||
	var b bytes.Buffer
 | 
			
		||||
	w := zlib.NewWriter(&b)
 | 
			
		||||
	w.Write([]byte("hello, world\n"))
 | 
			
		||||
	w.Close()
 | 
			
		||||
 | 
			
		||||
and to read that data back:
 | 
			
		||||
 | 
			
		||||
	r, err := zlib.NewReader(&b)
 | 
			
		||||
	io.Copy(os.Stdout, r)
 | 
			
		||||
	r.Close()
 | 
			
		||||
*/
 | 
			
		||||
package zlib
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bufio"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"hash"
 | 
			
		||||
	"hash/adler32"
 | 
			
		||||
	"io"
 | 
			
		||||
 | 
			
		||||
	"github.com/klauspost/compress/flate"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const zlibDeflate = 8
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	// ErrChecksum is returned when reading ZLIB data that has an invalid checksum.
 | 
			
		||||
	ErrChecksum = errors.New("zlib: invalid checksum")
 | 
			
		||||
	// ErrDictionary is returned when reading ZLIB data that has an invalid dictionary.
 | 
			
		||||
	ErrDictionary = errors.New("zlib: invalid dictionary")
 | 
			
		||||
	// ErrHeader is returned when reading ZLIB data that has an invalid header.
 | 
			
		||||
	ErrHeader = errors.New("zlib: invalid header")
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type reader struct {
 | 
			
		||||
	r            flate.Reader
 | 
			
		||||
	decompressor io.ReadCloser
 | 
			
		||||
	digest       hash.Hash32
 | 
			
		||||
	err          error
 | 
			
		||||
	scratch      [4]byte
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Resetter resets a ReadCloser returned by NewReader or NewReaderDict to
 | 
			
		||||
// to switch to a new underlying Reader. This permits reusing a ReadCloser
 | 
			
		||||
// instead of allocating a new one.
 | 
			
		||||
type Resetter interface {
 | 
			
		||||
	// Reset discards any buffered data and resets the Resetter as if it was
 | 
			
		||||
	// newly initialized with the given reader.
 | 
			
		||||
	Reset(r io.Reader, dict []byte) error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewReader creates a new ReadCloser.
 | 
			
		||||
// Reads from the returned ReadCloser read and decompress data from r.
 | 
			
		||||
// If r does not implement io.ByteReader, the decompressor may read more
 | 
			
		||||
// data than necessary from r.
 | 
			
		||||
// It is the caller's responsibility to call Close on the ReadCloser when done.
 | 
			
		||||
//
 | 
			
		||||
// The ReadCloser returned by NewReader also implements Resetter.
 | 
			
		||||
func NewReader(r io.Reader) (io.ReadCloser, error) {
 | 
			
		||||
	return NewReaderDict(r, nil)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewReaderDict is like NewReader but uses a preset dictionary.
 | 
			
		||||
// NewReaderDict ignores the dictionary if the compressed data does not refer to it.
 | 
			
		||||
// If the compressed data refers to a different dictionary, NewReaderDict returns ErrDictionary.
 | 
			
		||||
//
 | 
			
		||||
// The ReadCloser returned by NewReaderDict also implements Resetter.
 | 
			
		||||
func NewReaderDict(r io.Reader, dict []byte) (io.ReadCloser, error) {
 | 
			
		||||
	z := new(reader)
 | 
			
		||||
	err := z.Reset(r, dict)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return z, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (z *reader) Read(p []byte) (int, error) {
 | 
			
		||||
	if z.err != nil {
 | 
			
		||||
		return 0, z.err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var n int
 | 
			
		||||
	n, z.err = z.decompressor.Read(p)
 | 
			
		||||
	z.digest.Write(p[0:n])
 | 
			
		||||
	if z.err != io.EOF {
 | 
			
		||||
		// In the normal case we return here.
 | 
			
		||||
		return n, z.err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Finished file; check checksum.
 | 
			
		||||
	if _, err := io.ReadFull(z.r, z.scratch[0:4]); err != nil {
 | 
			
		||||
		if err == io.EOF {
 | 
			
		||||
			err = io.ErrUnexpectedEOF
 | 
			
		||||
		}
 | 
			
		||||
		z.err = err
 | 
			
		||||
		return n, z.err
 | 
			
		||||
	}
 | 
			
		||||
	// ZLIB (RFC 1950) is big-endian, unlike GZIP (RFC 1952).
 | 
			
		||||
	checksum := uint32(z.scratch[0])<<24 | uint32(z.scratch[1])<<16 | uint32(z.scratch[2])<<8 | uint32(z.scratch[3])
 | 
			
		||||
	if checksum != z.digest.Sum32() {
 | 
			
		||||
		z.err = ErrChecksum
 | 
			
		||||
		return n, z.err
 | 
			
		||||
	}
 | 
			
		||||
	return n, io.EOF
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Calling Close does not close the wrapped io.Reader originally passed to NewReader.
 | 
			
		||||
// In order for the ZLIB checksum to be verified, the reader must be
 | 
			
		||||
// fully consumed until the io.EOF.
 | 
			
		||||
func (z *reader) Close() error {
 | 
			
		||||
	if z.err != nil && z.err != io.EOF {
 | 
			
		||||
		return z.err
 | 
			
		||||
	}
 | 
			
		||||
	z.err = z.decompressor.Close()
 | 
			
		||||
	return z.err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (z *reader) Reset(r io.Reader, dict []byte) error {
 | 
			
		||||
	*z = reader{decompressor: z.decompressor}
 | 
			
		||||
	if fr, ok := r.(flate.Reader); ok {
 | 
			
		||||
		z.r = fr
 | 
			
		||||
	} else {
 | 
			
		||||
		z.r = bufio.NewReader(r)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Read the header (RFC 1950 section 2.2.).
 | 
			
		||||
	_, z.err = io.ReadFull(z.r, z.scratch[0:2])
 | 
			
		||||
	if z.err != nil {
 | 
			
		||||
		if z.err == io.EOF {
 | 
			
		||||
			z.err = io.ErrUnexpectedEOF
 | 
			
		||||
		}
 | 
			
		||||
		return z.err
 | 
			
		||||
	}
 | 
			
		||||
	h := uint(z.scratch[0])<<8 | uint(z.scratch[1])
 | 
			
		||||
	if (z.scratch[0]&0x0f != zlibDeflate) || (h%31 != 0) {
 | 
			
		||||
		z.err = ErrHeader
 | 
			
		||||
		return z.err
 | 
			
		||||
	}
 | 
			
		||||
	haveDict := z.scratch[1]&0x20 != 0
 | 
			
		||||
	if haveDict {
 | 
			
		||||
		_, z.err = io.ReadFull(z.r, z.scratch[0:4])
 | 
			
		||||
		if z.err != nil {
 | 
			
		||||
			if z.err == io.EOF {
 | 
			
		||||
				z.err = io.ErrUnexpectedEOF
 | 
			
		||||
			}
 | 
			
		||||
			return z.err
 | 
			
		||||
		}
 | 
			
		||||
		checksum := uint32(z.scratch[0])<<24 | uint32(z.scratch[1])<<16 | uint32(z.scratch[2])<<8 | uint32(z.scratch[3])
 | 
			
		||||
		if checksum != adler32.Checksum(dict) {
 | 
			
		||||
			z.err = ErrDictionary
 | 
			
		||||
			return z.err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if z.decompressor == nil {
 | 
			
		||||
		if haveDict {
 | 
			
		||||
			z.decompressor = flate.NewReaderDict(z.r, dict)
 | 
			
		||||
		} else {
 | 
			
		||||
			z.decompressor = flate.NewReader(z.r)
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		z.decompressor.(flate.Resetter).Reset(z.r, dict)
 | 
			
		||||
	}
 | 
			
		||||
	z.digest = adler32.New()
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										179
									
								
								vendor/github.com/klauspost/compress/zlib/reader_test.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										179
									
								
								vendor/github.com/klauspost/compress/zlib/reader_test.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,179 @@
 | 
			
		||||
// Copyright 2009 The Go Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a BSD-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
package zlib
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"io"
 | 
			
		||||
	"testing"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type zlibTest struct {
 | 
			
		||||
	desc       string
 | 
			
		||||
	raw        string
 | 
			
		||||
	compressed []byte
 | 
			
		||||
	dict       []byte
 | 
			
		||||
	err        error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Compare-to-golden test data was generated by the ZLIB example program at
 | 
			
		||||
// http://www.zlib.net/zpipe.c
 | 
			
		||||
 | 
			
		||||
var zlibTests = []zlibTest{
 | 
			
		||||
	{
 | 
			
		||||
		"truncated empty",
 | 
			
		||||
		"",
 | 
			
		||||
		[]byte{},
 | 
			
		||||
		nil,
 | 
			
		||||
		io.ErrUnexpectedEOF,
 | 
			
		||||
	},
 | 
			
		||||
	{
 | 
			
		||||
		"truncated dict",
 | 
			
		||||
		"",
 | 
			
		||||
		[]byte{0x78, 0xbb},
 | 
			
		||||
		[]byte{0x00},
 | 
			
		||||
		io.ErrUnexpectedEOF,
 | 
			
		||||
	},
 | 
			
		||||
	{
 | 
			
		||||
		"truncated checksum",
 | 
			
		||||
		"",
 | 
			
		||||
		[]byte{0x78, 0xbb, 0x00, 0x01, 0x00, 0x01, 0xca, 0x48,
 | 
			
		||||
			0xcd, 0xc9, 0xc9, 0xd7, 0x51, 0x28, 0xcf, 0x2f,
 | 
			
		||||
			0xca, 0x49, 0x01, 0x04, 0x00, 0x00, 0xff, 0xff,
 | 
			
		||||
		},
 | 
			
		||||
		[]byte{0x00},
 | 
			
		||||
		io.ErrUnexpectedEOF,
 | 
			
		||||
	},
 | 
			
		||||
	{
 | 
			
		||||
		"empty",
 | 
			
		||||
		"",
 | 
			
		||||
		[]byte{0x78, 0x9c, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01},
 | 
			
		||||
		nil,
 | 
			
		||||
		nil,
 | 
			
		||||
	},
 | 
			
		||||
	{
 | 
			
		||||
		"goodbye",
 | 
			
		||||
		"goodbye, world",
 | 
			
		||||
		[]byte{
 | 
			
		||||
			0x78, 0x9c, 0x4b, 0xcf, 0xcf, 0x4f, 0x49, 0xaa,
 | 
			
		||||
			0x4c, 0xd5, 0x51, 0x28, 0xcf, 0x2f, 0xca, 0x49,
 | 
			
		||||
			0x01, 0x00, 0x28, 0xa5, 0x05, 0x5e,
 | 
			
		||||
		},
 | 
			
		||||
		nil,
 | 
			
		||||
		nil,
 | 
			
		||||
	},
 | 
			
		||||
	{
 | 
			
		||||
		"bad header",
 | 
			
		||||
		"",
 | 
			
		||||
		[]byte{0x78, 0x9f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01},
 | 
			
		||||
		nil,
 | 
			
		||||
		ErrHeader,
 | 
			
		||||
	},
 | 
			
		||||
	{
 | 
			
		||||
		"bad checksum",
 | 
			
		||||
		"",
 | 
			
		||||
		[]byte{0x78, 0x9c, 0x03, 0x00, 0x00, 0x00, 0x00, 0xff},
 | 
			
		||||
		nil,
 | 
			
		||||
		ErrChecksum,
 | 
			
		||||
	},
 | 
			
		||||
	{
 | 
			
		||||
		"not enough data",
 | 
			
		||||
		"",
 | 
			
		||||
		[]byte{0x78, 0x9c, 0x03, 0x00, 0x00, 0x00},
 | 
			
		||||
		nil,
 | 
			
		||||
		io.ErrUnexpectedEOF,
 | 
			
		||||
	},
 | 
			
		||||
	{
 | 
			
		||||
		"excess data is silently ignored",
 | 
			
		||||
		"",
 | 
			
		||||
		[]byte{
 | 
			
		||||
			0x78, 0x9c, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01,
 | 
			
		||||
			0x78, 0x9c, 0xff,
 | 
			
		||||
		},
 | 
			
		||||
		nil,
 | 
			
		||||
		nil,
 | 
			
		||||
	},
 | 
			
		||||
	{
 | 
			
		||||
		"dictionary",
 | 
			
		||||
		"Hello, World!\n",
 | 
			
		||||
		[]byte{
 | 
			
		||||
			0x78, 0xbb, 0x1c, 0x32, 0x04, 0x27, 0xf3, 0x00,
 | 
			
		||||
			0xb1, 0x75, 0x20, 0x1c, 0x45, 0x2e, 0x00, 0x24,
 | 
			
		||||
			0x12, 0x04, 0x74,
 | 
			
		||||
		},
 | 
			
		||||
		[]byte{
 | 
			
		||||
			0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x0a,
 | 
			
		||||
		},
 | 
			
		||||
		nil,
 | 
			
		||||
	},
 | 
			
		||||
	{
 | 
			
		||||
		"wrong dictionary",
 | 
			
		||||
		"",
 | 
			
		||||
		[]byte{
 | 
			
		||||
			0x78, 0xbb, 0x1c, 0x32, 0x04, 0x27, 0xf3, 0x00,
 | 
			
		||||
			0xb1, 0x75, 0x20, 0x1c, 0x45, 0x2e, 0x00, 0x24,
 | 
			
		||||
			0x12, 0x04, 0x74,
 | 
			
		||||
		},
 | 
			
		||||
		[]byte{
 | 
			
		||||
			0x48, 0x65, 0x6c, 0x6c,
 | 
			
		||||
		},
 | 
			
		||||
		ErrDictionary,
 | 
			
		||||
	},
 | 
			
		||||
	{
 | 
			
		||||
		"truncated zlib stream amid raw-block",
 | 
			
		||||
		"hello",
 | 
			
		||||
		[]byte{
 | 
			
		||||
			0x78, 0x9c, 0x00, 0x0c, 0x00, 0xf3, 0xff, 0x68, 0x65, 0x6c, 0x6c, 0x6f,
 | 
			
		||||
		},
 | 
			
		||||
		nil,
 | 
			
		||||
		io.ErrUnexpectedEOF,
 | 
			
		||||
	},
 | 
			
		||||
	{
 | 
			
		||||
		"truncated zlib stream amid fixed-block",
 | 
			
		||||
		"He",
 | 
			
		||||
		[]byte{
 | 
			
		||||
			0x78, 0x9c, 0xf2, 0x48, 0xcd,
 | 
			
		||||
		},
 | 
			
		||||
		nil,
 | 
			
		||||
		io.ErrUnexpectedEOF,
 | 
			
		||||
	},
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestDecompressor(t *testing.T) {
 | 
			
		||||
	b := new(bytes.Buffer)
 | 
			
		||||
	for _, tt := range zlibTests {
 | 
			
		||||
		in := bytes.NewReader(tt.compressed)
 | 
			
		||||
		zr, err := NewReaderDict(in, tt.dict)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			if err != tt.err {
 | 
			
		||||
				t.Errorf("%s: NewReader: %s", tt.desc, err)
 | 
			
		||||
			}
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		defer zr.Close()
 | 
			
		||||
 | 
			
		||||
		// Read and verify correctness of data.
 | 
			
		||||
		b.Reset()
 | 
			
		||||
		n, err := io.Copy(b, zr)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			if err != tt.err {
 | 
			
		||||
				t.Errorf("%s: io.Copy: %v want %v", tt.desc, err, tt.err)
 | 
			
		||||
			}
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		s := b.String()
 | 
			
		||||
		if s != tt.raw {
 | 
			
		||||
			t.Errorf("%s: got %d-byte %q want %d-byte %q", tt.desc, n, s, len(tt.raw), tt.raw)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Check for sticky errors.
 | 
			
		||||
		if n, err := zr.Read([]byte{0}); n != 0 || err != io.EOF {
 | 
			
		||||
			t.Errorf("%s: Read() = (%d, %v), want (0, io.EOF)", tt.desc, n, err)
 | 
			
		||||
		}
 | 
			
		||||
		if err := zr.Close(); err != nil {
 | 
			
		||||
			t.Errorf("%s: Close() = %v, want nil", tt.desc, err)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										201
									
								
								vendor/github.com/klauspost/compress/zlib/writer.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										201
									
								
								vendor/github.com/klauspost/compress/zlib/writer.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,201 @@
 | 
			
		||||
// Copyright 2009 The Go Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a BSD-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
package zlib
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"hash"
 | 
			
		||||
	"hash/adler32"
 | 
			
		||||
	"io"
 | 
			
		||||
 | 
			
		||||
	"github.com/klauspost/compress/flate"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// These constants are copied from the flate package, so that code that imports
 | 
			
		||||
// "compress/zlib" does not also have to import "compress/flate".
 | 
			
		||||
const (
 | 
			
		||||
	NoCompression       = flate.NoCompression
 | 
			
		||||
	BestSpeed           = flate.BestSpeed
 | 
			
		||||
	BestCompression     = flate.BestCompression
 | 
			
		||||
	DefaultCompression  = flate.DefaultCompression
 | 
			
		||||
	ConstantCompression = flate.ConstantCompression
 | 
			
		||||
	HuffmanOnly         = flate.HuffmanOnly
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// A Writer takes data written to it and writes the compressed
 | 
			
		||||
// form of that data to an underlying writer (see NewWriter).
 | 
			
		||||
type Writer struct {
 | 
			
		||||
	w           io.Writer
 | 
			
		||||
	level       int
 | 
			
		||||
	dict        []byte
 | 
			
		||||
	compressor  *flate.Writer
 | 
			
		||||
	digest      hash.Hash32
 | 
			
		||||
	err         error
 | 
			
		||||
	scratch     [4]byte
 | 
			
		||||
	wroteHeader bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewWriter creates a new Writer.
 | 
			
		||||
// Writes to the returned Writer are compressed and written to w.
 | 
			
		||||
//
 | 
			
		||||
// It is the caller's responsibility to call Close on the WriteCloser when done.
 | 
			
		||||
// Writes may be buffered and not flushed until Close.
 | 
			
		||||
func NewWriter(w io.Writer) *Writer {
 | 
			
		||||
	z, _ := NewWriterLevelDict(w, DefaultCompression, nil)
 | 
			
		||||
	return z
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewWriterLevel is like NewWriter but specifies the compression level instead
 | 
			
		||||
// of assuming DefaultCompression.
 | 
			
		||||
//
 | 
			
		||||
// The compression level can be DefaultCompression, NoCompression, HuffmanOnly
 | 
			
		||||
// or any integer value between BestSpeed and BestCompression inclusive.
 | 
			
		||||
// The error returned will be nil if the level is valid.
 | 
			
		||||
func NewWriterLevel(w io.Writer, level int) (*Writer, error) {
 | 
			
		||||
	return NewWriterLevelDict(w, level, nil)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewWriterLevelDict is like NewWriterLevel but specifies a dictionary to
 | 
			
		||||
// compress with.
 | 
			
		||||
//
 | 
			
		||||
// The dictionary may be nil. If not, its contents should not be modified until
 | 
			
		||||
// the Writer is closed.
 | 
			
		||||
func NewWriterLevelDict(w io.Writer, level int, dict []byte) (*Writer, error) {
 | 
			
		||||
	if level < HuffmanOnly || level > BestCompression {
 | 
			
		||||
		return nil, fmt.Errorf("zlib: invalid compression level: %d", level)
 | 
			
		||||
	}
 | 
			
		||||
	return &Writer{
 | 
			
		||||
		w:     w,
 | 
			
		||||
		level: level,
 | 
			
		||||
		dict:  dict,
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Reset clears the state of the Writer z such that it is equivalent to its
 | 
			
		||||
// initial state from NewWriterLevel or NewWriterLevelDict, but instead writing
 | 
			
		||||
// to w.
 | 
			
		||||
func (z *Writer) Reset(w io.Writer) {
 | 
			
		||||
	z.w = w
 | 
			
		||||
	// z.level and z.dict left unchanged.
 | 
			
		||||
	if z.compressor != nil {
 | 
			
		||||
		z.compressor.Reset(w)
 | 
			
		||||
	}
 | 
			
		||||
	if z.digest != nil {
 | 
			
		||||
		z.digest.Reset()
 | 
			
		||||
	}
 | 
			
		||||
	z.err = nil
 | 
			
		||||
	z.scratch = [4]byte{}
 | 
			
		||||
	z.wroteHeader = false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// writeHeader writes the ZLIB header.
 | 
			
		||||
func (z *Writer) writeHeader() (err error) {
 | 
			
		||||
	z.wroteHeader = true
 | 
			
		||||
	// ZLIB has a two-byte header (as documented in RFC 1950).
 | 
			
		||||
	// The first four bits is the CINFO (compression info), which is 7 for the default deflate window size.
 | 
			
		||||
	// The next four bits is the CM (compression method), which is 8 for deflate.
 | 
			
		||||
	z.scratch[0] = 0x78
 | 
			
		||||
	// The next two bits is the FLEVEL (compression level). The four values are:
 | 
			
		||||
	// 0=fastest, 1=fast, 2=default, 3=best.
 | 
			
		||||
	// The next bit, FDICT, is set if a dictionary is given.
 | 
			
		||||
	// The final five FCHECK bits form a mod-31 checksum.
 | 
			
		||||
	switch z.level {
 | 
			
		||||
	case -2, 0, 1:
 | 
			
		||||
		z.scratch[1] = 0 << 6
 | 
			
		||||
	case 2, 3, 4, 5:
 | 
			
		||||
		z.scratch[1] = 1 << 6
 | 
			
		||||
	case 6, -1:
 | 
			
		||||
		z.scratch[1] = 2 << 6
 | 
			
		||||
	case 7, 8, 9:
 | 
			
		||||
		z.scratch[1] = 3 << 6
 | 
			
		||||
	default:
 | 
			
		||||
		panic("unreachable")
 | 
			
		||||
	}
 | 
			
		||||
	if z.dict != nil {
 | 
			
		||||
		z.scratch[1] |= 1 << 5
 | 
			
		||||
	}
 | 
			
		||||
	z.scratch[1] += uint8(31 - (uint16(z.scratch[0])<<8+uint16(z.scratch[1]))%31)
 | 
			
		||||
	if _, err = z.w.Write(z.scratch[0:2]); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if z.dict != nil {
 | 
			
		||||
		// The next four bytes are the Adler-32 checksum of the dictionary.
 | 
			
		||||
		checksum := adler32.Checksum(z.dict)
 | 
			
		||||
		z.scratch[0] = uint8(checksum >> 24)
 | 
			
		||||
		z.scratch[1] = uint8(checksum >> 16)
 | 
			
		||||
		z.scratch[2] = uint8(checksum >> 8)
 | 
			
		||||
		z.scratch[3] = uint8(checksum >> 0)
 | 
			
		||||
		if _, err = z.w.Write(z.scratch[0:4]); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if z.compressor == nil {
 | 
			
		||||
		// Initialize deflater unless the Writer is being reused
 | 
			
		||||
		// after a Reset call.
 | 
			
		||||
		z.compressor, err = flate.NewWriterDict(z.w, z.level, z.dict)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		z.digest = adler32.New()
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Write writes a compressed form of p to the underlying io.Writer. The
 | 
			
		||||
// compressed bytes are not necessarily flushed until the Writer is closed or
 | 
			
		||||
// explicitly flushed.
 | 
			
		||||
func (z *Writer) Write(p []byte) (n int, err error) {
 | 
			
		||||
	if !z.wroteHeader {
 | 
			
		||||
		z.err = z.writeHeader()
 | 
			
		||||
	}
 | 
			
		||||
	if z.err != nil {
 | 
			
		||||
		return 0, z.err
 | 
			
		||||
	}
 | 
			
		||||
	if len(p) == 0 {
 | 
			
		||||
		return 0, nil
 | 
			
		||||
	}
 | 
			
		||||
	n, err = z.compressor.Write(p)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		z.err = err
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	z.digest.Write(p)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Flush flushes the Writer to its underlying io.Writer.
 | 
			
		||||
func (z *Writer) Flush() error {
 | 
			
		||||
	if !z.wroteHeader {
 | 
			
		||||
		z.err = z.writeHeader()
 | 
			
		||||
	}
 | 
			
		||||
	if z.err != nil {
 | 
			
		||||
		return z.err
 | 
			
		||||
	}
 | 
			
		||||
	z.err = z.compressor.Flush()
 | 
			
		||||
	return z.err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Close closes the Writer, flushing any unwritten data to the underlying
 | 
			
		||||
// io.Writer, but does not close the underlying io.Writer.
 | 
			
		||||
func (z *Writer) Close() error {
 | 
			
		||||
	if !z.wroteHeader {
 | 
			
		||||
		z.err = z.writeHeader()
 | 
			
		||||
	}
 | 
			
		||||
	if z.err != nil {
 | 
			
		||||
		return z.err
 | 
			
		||||
	}
 | 
			
		||||
	z.err = z.compressor.Close()
 | 
			
		||||
	if z.err != nil {
 | 
			
		||||
		return z.err
 | 
			
		||||
	}
 | 
			
		||||
	checksum := z.digest.Sum32()
 | 
			
		||||
	// ZLIB (RFC 1950) is big-endian, unlike GZIP (RFC 1952).
 | 
			
		||||
	z.scratch[0] = uint8(checksum >> 24)
 | 
			
		||||
	z.scratch[1] = uint8(checksum >> 16)
 | 
			
		||||
	z.scratch[2] = uint8(checksum >> 8)
 | 
			
		||||
	z.scratch[3] = uint8(checksum >> 0)
 | 
			
		||||
	_, z.err = z.w.Write(z.scratch[0:4])
 | 
			
		||||
	return z.err
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										212
									
								
								vendor/github.com/klauspost/compress/zlib/writer_test.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										212
									
								
								vendor/github.com/klauspost/compress/zlib/writer_test.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,212 @@
 | 
			
		||||
// Copyright 2009 The Go Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a BSD-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
package zlib
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"os"
 | 
			
		||||
	"testing"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var filenames = []string{
 | 
			
		||||
	"../testdata/gettysburg.txt",
 | 
			
		||||
	"../testdata/e.txt",
 | 
			
		||||
	"../testdata/pi.txt",
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var data = []string{
 | 
			
		||||
	"test a reasonable sized string that can be compressed",
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Tests that compressing and then decompressing the given file at the given compression level and dictionary
 | 
			
		||||
// yields equivalent bytes to the original file.
 | 
			
		||||
func testFileLevelDict(t *testing.T, fn string, level int, d string) {
 | 
			
		||||
	// Read the file, as golden output.
 | 
			
		||||
	golden, err := os.Open(fn)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	defer golden.Close()
 | 
			
		||||
	b0, err0 := ioutil.ReadAll(golden)
 | 
			
		||||
	if err0 != nil {
 | 
			
		||||
		t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err0)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	testLevelDict(t, fn, b0, level, d)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func testLevelDict(t *testing.T, fn string, b0 []byte, level int, d string) {
 | 
			
		||||
	// Make dictionary, if given.
 | 
			
		||||
	var dict []byte
 | 
			
		||||
	if d != "" {
 | 
			
		||||
		dict = []byte(d)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Push data through a pipe that compresses at the write end, and decompresses at the read end.
 | 
			
		||||
	piper, pipew := io.Pipe()
 | 
			
		||||
	defer piper.Close()
 | 
			
		||||
	go func() {
 | 
			
		||||
		defer pipew.Close()
 | 
			
		||||
		zlibw, err := NewWriterLevelDict(pipew, level, dict)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		defer zlibw.Close()
 | 
			
		||||
		_, err = zlibw.Write(b0)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
	}()
 | 
			
		||||
	zlibr, err := NewReaderDict(piper, dict)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	defer zlibr.Close()
 | 
			
		||||
 | 
			
		||||
	// Compare the decompressed data.
 | 
			
		||||
	b1, err1 := ioutil.ReadAll(zlibr)
 | 
			
		||||
	if err1 != nil {
 | 
			
		||||
		t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err1)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	if len(b0) != len(b1) {
 | 
			
		||||
		t.Errorf("%s (level=%d, dict=%q): length mismatch %d versus %d", fn, level, d, len(b0), len(b1))
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	for i := 0; i < len(b0); i++ {
 | 
			
		||||
		if b0[i] != b1[i] {
 | 
			
		||||
			t.Errorf("%s (level=%d, dict=%q): mismatch at %d, 0x%02x versus 0x%02x\n", fn, level, d, i, b0[i], b1[i])
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func testFileLevelDictReset(t *testing.T, fn string, level int, dict []byte) {
 | 
			
		||||
	var b0 []byte
 | 
			
		||||
	var err error
 | 
			
		||||
	if fn != "" {
 | 
			
		||||
		b0, err = ioutil.ReadFile(fn)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			t.Errorf("%s (level=%d): %v", fn, level, err)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Compress once.
 | 
			
		||||
	buf := new(bytes.Buffer)
 | 
			
		||||
	var zlibw *Writer
 | 
			
		||||
	if dict == nil {
 | 
			
		||||
		zlibw, err = NewWriterLevel(buf, level)
 | 
			
		||||
	} else {
 | 
			
		||||
		zlibw, err = NewWriterLevelDict(buf, level, dict)
 | 
			
		||||
	}
 | 
			
		||||
	if err == nil {
 | 
			
		||||
		_, err = zlibw.Write(b0)
 | 
			
		||||
	}
 | 
			
		||||
	if err == nil {
 | 
			
		||||
		err = zlibw.Close()
 | 
			
		||||
	}
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Errorf("%s (level=%d): %v", fn, level, err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	out := buf.String()
 | 
			
		||||
 | 
			
		||||
	// Reset and compress again.
 | 
			
		||||
	buf2 := new(bytes.Buffer)
 | 
			
		||||
	zlibw.Reset(buf2)
 | 
			
		||||
	_, err = zlibw.Write(b0)
 | 
			
		||||
	if err == nil {
 | 
			
		||||
		err = zlibw.Close()
 | 
			
		||||
	}
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Errorf("%s (level=%d): %v", fn, level, err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	out2 := buf2.String()
 | 
			
		||||
 | 
			
		||||
	if out2 != out {
 | 
			
		||||
		t.Errorf("%s (level=%d): different output after reset (got %d bytes, expected %d",
 | 
			
		||||
			fn, level, len(out2), len(out))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestWriter(t *testing.T) {
 | 
			
		||||
	for i, s := range data {
 | 
			
		||||
		b := []byte(s)
 | 
			
		||||
		tag := fmt.Sprintf("#%d", i)
 | 
			
		||||
		testLevelDict(t, tag, b, DefaultCompression, "")
 | 
			
		||||
		testLevelDict(t, tag, b, NoCompression, "")
 | 
			
		||||
		testLevelDict(t, tag, b, HuffmanOnly, "")
 | 
			
		||||
		for level := BestSpeed; level <= BestCompression; level++ {
 | 
			
		||||
			testLevelDict(t, tag, b, level, "")
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestWriterBig(t *testing.T) {
 | 
			
		||||
	for _, fn := range filenames {
 | 
			
		||||
		testFileLevelDict(t, fn, DefaultCompression, "")
 | 
			
		||||
		testFileLevelDict(t, fn, NoCompression, "")
 | 
			
		||||
		testFileLevelDict(t, fn, HuffmanOnly, "")
 | 
			
		||||
		for level := BestSpeed; level <= BestCompression; level++ {
 | 
			
		||||
			testFileLevelDict(t, fn, level, "")
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestWriterDict(t *testing.T) {
 | 
			
		||||
	const dictionary = "0123456789."
 | 
			
		||||
	for _, fn := range filenames {
 | 
			
		||||
		testFileLevelDict(t, fn, DefaultCompression, dictionary)
 | 
			
		||||
		testFileLevelDict(t, fn, NoCompression, dictionary)
 | 
			
		||||
		testFileLevelDict(t, fn, HuffmanOnly, dictionary)
 | 
			
		||||
		for level := BestSpeed; level <= BestCompression; level++ {
 | 
			
		||||
			testFileLevelDict(t, fn, level, dictionary)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestWriterReset(t *testing.T) {
 | 
			
		||||
	const dictionary = "0123456789."
 | 
			
		||||
	for _, fn := range filenames {
 | 
			
		||||
		testFileLevelDictReset(t, fn, NoCompression, nil)
 | 
			
		||||
		testFileLevelDictReset(t, fn, DefaultCompression, nil)
 | 
			
		||||
		testFileLevelDictReset(t, fn, HuffmanOnly, nil)
 | 
			
		||||
		testFileLevelDictReset(t, fn, NoCompression, []byte(dictionary))
 | 
			
		||||
		testFileLevelDictReset(t, fn, DefaultCompression, []byte(dictionary))
 | 
			
		||||
		testFileLevelDictReset(t, fn, HuffmanOnly, []byte(dictionary))
 | 
			
		||||
		if testing.Short() {
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
		for level := BestSpeed; level <= BestCompression; level++ {
 | 
			
		||||
			testFileLevelDictReset(t, fn, level, nil)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestWriterDictIsUsed(t *testing.T) {
 | 
			
		||||
	var input = []byte("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.")
 | 
			
		||||
	var buf bytes.Buffer
 | 
			
		||||
	compressor, err := NewWriterLevelDict(&buf, BestCompression, input)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Errorf("error in NewWriterLevelDict: %s", err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	compressor.Write(input)
 | 
			
		||||
	compressor.Close()
 | 
			
		||||
	const expectedMaxSize = 25
 | 
			
		||||
	output := buf.Bytes()
 | 
			
		||||
	if len(output) > expectedMaxSize {
 | 
			
		||||
		t.Errorf("result too large (got %d, want <= %d bytes). Is the dictionary being used?", len(output), expectedMaxSize)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user