register.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. // Copyright 2010 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package zip
  5. import (
  6. "errors"
  7. "io"
  8. "io/ioutil"
  9. "sync"
  10. "github.com/klauspost/compress/flate"
  11. )
  12. // A Compressor returns a new compressing writer, writing to w.
  13. // The WriteCloser's Close method must be used to flush pending data to w.
  14. // The Compressor itself must be safe to invoke from multiple goroutines
  15. // simultaneously, but each returned writer will be used only by
  16. // one goroutine at a time.
  17. type Compressor func(w io.Writer) (io.WriteCloser, error)
  18. // A Decompressor returns a new decompressing reader, reading from r.
  19. // The ReadCloser's Close method must be used to release associated resources.
  20. // The Decompressor itself must be safe to invoke from multiple goroutines
  21. // simultaneously, but each returned reader will be used only by
  22. // one goroutine at a time.
  23. type Decompressor func(r io.Reader) io.ReadCloser
  24. var flateWriterPool sync.Pool
  25. func newFlateWriter(w io.Writer) io.WriteCloser {
  26. fw, ok := flateWriterPool.Get().(*flate.Writer)
  27. if ok {
  28. fw.Reset(w)
  29. } else {
  30. fw, _ = flate.NewWriter(w, 5)
  31. }
  32. return &pooledFlateWriter{fw: fw}
  33. }
  34. type pooledFlateWriter struct {
  35. mu sync.Mutex // guards Close and Write
  36. fw *flate.Writer
  37. }
  38. func (w *pooledFlateWriter) Write(p []byte) (n int, err error) {
  39. w.mu.Lock()
  40. defer w.mu.Unlock()
  41. if w.fw == nil {
  42. return 0, errors.New("Write after Close")
  43. }
  44. return w.fw.Write(p)
  45. }
  46. func (w *pooledFlateWriter) Close() error {
  47. w.mu.Lock()
  48. defer w.mu.Unlock()
  49. var err error
  50. if w.fw != nil {
  51. err = w.fw.Close()
  52. flateWriterPool.Put(w.fw)
  53. w.fw = nil
  54. }
  55. return err
  56. }
  57. var flateReaderPool sync.Pool
  58. func newFlateReader(r io.Reader) io.ReadCloser {
  59. fr, ok := flateReaderPool.Get().(io.ReadCloser)
  60. if ok {
  61. fr.(flate.Resetter).Reset(r, nil)
  62. } else {
  63. fr = flate.NewReader(r)
  64. }
  65. return &pooledFlateReader{fr: fr}
  66. }
  67. type pooledFlateReader struct {
  68. mu sync.Mutex // guards Close and Read
  69. fr io.ReadCloser
  70. }
  71. func (r *pooledFlateReader) Read(p []byte) (n int, err error) {
  72. r.mu.Lock()
  73. defer r.mu.Unlock()
  74. if r.fr == nil {
  75. return 0, errors.New("Read after Close")
  76. }
  77. return r.fr.Read(p)
  78. }
  79. func (r *pooledFlateReader) Close() error {
  80. r.mu.Lock()
  81. defer r.mu.Unlock()
  82. var err error
  83. if r.fr != nil {
  84. err = r.fr.Close()
  85. flateReaderPool.Put(r.fr)
  86. r.fr = nil
  87. }
  88. return err
  89. }
  90. var (
  91. compressors sync.Map // map[uint16]Compressor
  92. decompressors sync.Map // map[uint16]Decompressor
  93. )
  94. func init() {
  95. compressors.Store(Store, Compressor(func(w io.Writer) (io.WriteCloser, error) { return &nopCloser{w}, nil }))
  96. compressors.Store(Deflate, Compressor(func(w io.Writer) (io.WriteCloser, error) { return newFlateWriter(w), nil }))
  97. decompressors.Store(Store, Decompressor(ioutil.NopCloser))
  98. decompressors.Store(Deflate, Decompressor(newFlateReader))
  99. }
  100. // RegisterDecompressor allows custom decompressors for a specified method ID.
  101. // The common methods Store and Deflate are built in.
  102. func RegisterDecompressor(method uint16, dcomp Decompressor) {
  103. if _, dup := decompressors.LoadOrStore(method, dcomp); dup {
  104. panic("decompressor already registered")
  105. }
  106. }
  107. // RegisterCompressor registers custom compressors for a specified method ID.
  108. // The common methods Store and Deflate are built in.
  109. func RegisterCompressor(method uint16, comp Compressor) {
  110. if _, dup := compressors.LoadOrStore(method, comp); dup {
  111. panic("compressor already registered")
  112. }
  113. }
  114. func compressor(method uint16) Compressor {
  115. ci, ok := compressors.Load(method)
  116. if !ok {
  117. return nil
  118. }
  119. return ci.(Compressor)
  120. }
  121. func decompressor(method uint16) Decompressor {
  122. di, ok := decompressors.Load(method)
  123. if !ok {
  124. return nil
  125. }
  126. return di.(Decompressor)
  127. }