go-hep.org/x/hep@v0.38.1/rio/compressor.go (about) 1 // Copyright ©2015 The go-hep 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 5 package rio 6 7 import ( 8 "compress/flate" 9 "compress/gzip" 10 "compress/zlib" 11 "fmt" 12 "io" 13 ) 14 15 // A Compressor takes data written to it and writes the compressed form of that 16 // data to an underlying writer. 17 type Compressor interface { 18 io.WriteCloser 19 20 // Reset clears the state of the Writer such that it is equivalent to its 21 // initial state, but instead writing to w. 22 Reset(w io.Writer) error 23 24 // Flush flushes the Writer to its underlying io.Writer. 25 Flush() error 26 27 // Kind returns the (de)compressor kind 28 //Kind() CompressorKind 29 } 30 31 // A Decompressor reads data from the underlying io.Reader and decompresses it. 32 type Decompressor interface { 33 io.ReadCloser 34 35 // Reset clears the state of the Reader such that it is equivalent to its 36 // initial state, but instead reading from r. 37 Reset(r io.Reader) error 38 39 // Kind returns the (de)compressor kind 40 //Kind() CompressorKind 41 } 42 43 // Xpressor provides compressor and decompressor functions 44 type Xpressor interface { 45 Inflate(r io.Reader) (Decompressor, error) 46 Deflate(w io.Writer, opts Options) (Compressor, error) 47 } 48 49 // CompressorKind names the various compressors 50 type CompressorKind uint16 51 52 // builtin compressor types 53 const ( 54 CompressDefault CompressorKind = iota 55 CompressNone 56 CompressFlate 57 CompressZlib 58 CompressGzip 59 CompressLZA 60 CompressLZO 61 CompressSnappy 62 63 CompressUser CompressorKind = 0xffff // keep last 64 ) 65 66 func (ck CompressorKind) String() string { 67 switch ck { 68 case CompressUser: 69 return "user" 70 case CompressDefault: 71 return "default" 72 case CompressNone: 73 return "none" 74 case CompressFlate: 75 return "flate" 76 case CompressZlib: 77 return "zlib" 78 case CompressGzip: 79 return "gzip" 80 case CompressLZA: 81 return "lza" 82 case CompressLZO: 83 return "lzo" 84 case CompressSnappy: 85 return "snappy" 86 } 87 return "N/A" 88 } 89 90 // NewCompressor creates a Compressor writing to w, with compression level according to opts. 91 func (ck CompressorKind) NewCompressor(w io.Writer, opts Options) (Compressor, error) { 92 x, ok := xcomprs[ck] 93 if !ok { 94 return nil, fmt.Errorf("rio: no compressor registered with %q (%v)", ck.String(), int(ck)) 95 } 96 return x.Deflate(w, opts) 97 } 98 99 // NewDecompressor creates a Decompressor reading from r. 100 func (ck CompressorKind) NewDecompressor(r io.Reader) (Decompressor, error) { 101 x, ok := xcomprs[ck] 102 if !ok { 103 return nil, fmt.Errorf("rio: no decompressor registered with %q (%v)", ck.String(), int(ck)) 104 } 105 return x.Inflate(r) 106 } 107 108 type xpressor struct { 109 inflater func(r io.Reader) (Decompressor, error) 110 deflater func(w io.Writer, opts Options) (Compressor, error) 111 } 112 113 func (x xpressor) Inflate(r io.Reader) (Decompressor, error) { 114 return x.inflater(r) 115 } 116 117 func (x xpressor) Deflate(w io.Writer, o Options) (Compressor, error) { 118 return x.deflater(w, o) 119 } 120 121 type noneCompressor struct{} 122 123 func (noneCompressor) Inflate(r io.Reader) (Decompressor, error) { 124 return &nopReadCloser{r}, nil 125 } 126 127 func (noneCompressor) Deflate(w io.Writer, o Options) (Compressor, error) { 128 return &nopWriteCloser{w}, nil 129 } 130 131 type nopWriteCloser struct { 132 io.Writer 133 } 134 135 func (nw *nopWriteCloser) Close() error { 136 return nil 137 } 138 139 func (nw *nopWriteCloser) Flush() error { 140 return nil 141 } 142 143 func (nw *nopWriteCloser) Reset(w io.Writer) error { 144 nw.Writer = w 145 return nil 146 } 147 148 type nopReadCloser struct { 149 io.Reader 150 } 151 152 func (nr *nopReadCloser) Close() error { 153 return nil 154 } 155 156 func (nr *nopReadCloser) Reset(r io.Reader) error { 157 nr.Reader = r 158 return nil 159 } 160 161 // flate --- 162 163 type flateCompressor struct { 164 *flate.Writer 165 } 166 167 func newFlateCompressor(w io.Writer, o Options) (Compressor, error) { 168 cw, err := flate.NewWriter(w, o.CompressorLevel()) 169 return &flateCompressor{cw}, err 170 } 171 172 func (cw *flateCompressor) Reset(w io.Writer) error { 173 cw.Writer.Reset(w) 174 return nil 175 } 176 177 type flateDecompressor struct { 178 io.ReadCloser 179 } 180 181 func newFlateDecompressor(r io.Reader) (Decompressor, error) { 182 xr := flate.NewReader(r) 183 return &flateDecompressor{xr}, nil 184 } 185 186 func (xr *flateDecompressor) Reset(r io.Reader) error { 187 return xr.ReadCloser.(flate.Resetter).Reset(r, nil) 188 } 189 190 // zlib --- 191 192 type zlibCompressor struct { 193 *zlib.Writer 194 } 195 196 func newZlibCompressor(w io.Writer, o Options) (Compressor, error) { 197 cw, err := zlib.NewWriterLevel(w, o.CompressorLevel()) 198 return &zlibCompressor{cw}, err 199 } 200 201 func (cw *zlibCompressor) Reset(w io.Writer) error { 202 cw.Writer.Reset(w) 203 return nil 204 } 205 206 type zlibDecompressor struct { 207 io.ReadCloser 208 } 209 210 func newZlibDecompressor(r io.Reader) (Decompressor, error) { 211 xr, err := zlib.NewReader(r) 212 return &zlibDecompressor{xr}, err 213 } 214 215 func (xr *zlibDecompressor) Reset(r io.Reader) error { 216 return xr.ReadCloser.(zlib.Resetter).Reset(r, nil) 217 } 218 219 // gzip --- 220 221 type gzipCompressor struct { 222 *gzip.Writer 223 } 224 225 func newGzipCompressor(w io.Writer, o Options) (Compressor, error) { 226 cw, err := gzip.NewWriterLevel(w, o.CompressorLevel()) 227 return &gzipCompressor{cw}, err 228 } 229 230 func (cw *gzipCompressor) Reset(w io.Writer) error { 231 cw.Writer.Reset(w) 232 return nil 233 } 234 235 type gzipDecompressor struct { 236 *gzip.Reader 237 } 238 239 func newGzipDecompressor(r io.Reader) (Decompressor, error) { 240 xr, err := gzip.NewReader(r) 241 return &gzipDecompressor{xr}, err 242 } 243 244 // RegisterCompressor registers a compressor/decompressor. 245 // It silently replaces the compressor/decompressor if one was already registered. 246 func RegisterCompressor(kind CompressorKind, x Xpressor) { 247 xcomprs[kind] = x 248 } 249 250 var xcomprs map[CompressorKind]Xpressor 251 252 func init() { 253 254 xcomprs = map[CompressorKind]Xpressor{ 255 256 CompressNone: noneCompressor{}, 257 258 CompressFlate: xpressor{ 259 inflater: newFlateDecompressor, 260 deflater: newFlateCompressor, 261 }, 262 263 CompressZlib: xpressor{ 264 inflater: newZlibDecompressor, 265 deflater: newZlibCompressor, 266 }, 267 268 CompressGzip: xpressor{ 269 inflater: newGzipDecompressor, 270 deflater: newGzipCompressor, 271 }, 272 } 273 274 xcomprs[CompressDefault] = xcomprs[CompressZlib] 275 }