1package restful
2
3// Copyright 2015 Ernest Micklei. All rights reserved.
4// Use of this source code is governed by a license
5// that can be found in the LICENSE file.
6
7import (
8	"bytes"
9	"compress/gzip"
10	"compress/zlib"
11	"sync"
12)
13
14// SyncPoolCompessors is a CompressorProvider that use the standard sync.Pool.
15type SyncPoolCompessors struct {
16	GzipWriterPool *sync.Pool
17	GzipReaderPool *sync.Pool
18	ZlibWriterPool *sync.Pool
19}
20
21// NewSyncPoolCompessors returns a new ("empty") SyncPoolCompessors.
22func NewSyncPoolCompessors() *SyncPoolCompessors {
23	return &SyncPoolCompessors{
24		GzipWriterPool: &sync.Pool{
25			New: func() interface{} { return newGzipWriter() },
26		},
27		GzipReaderPool: &sync.Pool{
28			New: func() interface{} { return newGzipReader() },
29		},
30		ZlibWriterPool: &sync.Pool{
31			New: func() interface{} { return newZlibWriter() },
32		},
33	}
34}
35
36func (s *SyncPoolCompessors) AcquireGzipWriter() *gzip.Writer {
37	return s.GzipWriterPool.Get().(*gzip.Writer)
38}
39
40func (s *SyncPoolCompessors) ReleaseGzipWriter(w *gzip.Writer) {
41	s.GzipWriterPool.Put(w)
42}
43
44func (s *SyncPoolCompessors) AcquireGzipReader() *gzip.Reader {
45	return s.GzipReaderPool.Get().(*gzip.Reader)
46}
47
48func (s *SyncPoolCompessors) ReleaseGzipReader(r *gzip.Reader) {
49	s.GzipReaderPool.Put(r)
50}
51
52func (s *SyncPoolCompessors) AcquireZlibWriter() *zlib.Writer {
53	return s.ZlibWriterPool.Get().(*zlib.Writer)
54}
55
56func (s *SyncPoolCompessors) ReleaseZlibWriter(w *zlib.Writer) {
57	s.ZlibWriterPool.Put(w)
58}
59
60func newGzipWriter() *gzip.Writer {
61	// create with an empty bytes writer; it will be replaced before using the gzipWriter
62	writer, err := gzip.NewWriterLevel(new(bytes.Buffer), gzip.BestSpeed)
63	if err != nil {
64		panic(err.Error())
65	}
66	return writer
67}
68
69func newGzipReader() *gzip.Reader {
70	// create with an empty reader (but with GZIP header); it will be replaced before using the gzipReader
71	// we can safely use currentCompressProvider because it is set on package initialization.
72	w := currentCompressorProvider.AcquireGzipWriter()
73	defer currentCompressorProvider.ReleaseGzipWriter(w)
74	b := new(bytes.Buffer)
75	w.Reset(b)
76	w.Flush()
77	w.Close()
78	reader, err := gzip.NewReader(bytes.NewReader(b.Bytes()))
79	if err != nil {
80		panic(err.Error())
81	}
82	return reader
83}
84
85func newZlibWriter() *zlib.Writer {
86	writer, err := zlib.NewWriterLevel(new(bytes.Buffer), gzip.BestSpeed)
87	if err != nil {
88		panic(err.Error())
89	}
90	return writer
91}
92