-
Notifications
You must be signed in to change notification settings - Fork 2
/
compress.go
168 lines (138 loc) · 3.17 KB
/
compress.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
package compress
import (
"bytes"
"fmt"
"io"
)
var algorithms = make(map[string]Algorithm)
// Algorithm interface.
type Algorithm interface {
NewAlgorithm() Algorithm
Ext() string
NewEncoder(w io.Writer) (Encoder, error)
NewDecoder(r io.Reader) (Decoder, error)
Encode(v []byte) ([]byte, error)
Decode(v []byte) ([]byte, error)
SetLevel(level Level) error
SetLitWidth(width int) error
SetEndian(endian Endian) error
}
// Encoder interface.
type Encoder interface {
Write(v []byte) (int, error)
Close() error
}
// Decoder interface.
type Decoder interface {
Read(v []byte) (int, error)
Close() error
}
// Option variadic function.
type Option func(Algorithm) error
// Level compression level.
type Level int
const (
// NoCompression no compression.
NoCompression Level = 0
// BestSpeed best speed.
BestSpeed Level = 1
// BestCompression best compression.
BestCompression Level = 9
// DefaultCompression default compression.
DefaultCompression Level = -1
// HuffmanOnly huffman only.
HuffmanOnly Level = -2
)
// Endian the order in which bytes are arranged into larger values.
type Endian int
const (
// Little endian LSB (Least Significant Bit).
Little Endian = 0
// Big endian MSB (Most Significant Bit).
Big Endian = 1
)
// Register algorithm.
func Register(name string, algorithm Algorithm) {
algorithms[name] = algorithm
}
// Algorithms registered.
func Algorithms() []string {
l := []string{}
for a := range algorithms {
l = append(l, a)
}
return l
}
// Registered is the algorithm registered.
func Registered(name string) error {
_, ok := algorithms[name]
if !ok {
return fmt.Errorf("algorithm not registered: %s", name)
}
return nil
}
// NewAlgorithm variadic constructor.
func NewAlgorithm(name string, opts ...Option) (Algorithm, error) {
a, ok := algorithms[name]
if !ok {
return nil, fmt.Errorf("algorithm not registered: %s", name)
}
a = a.NewAlgorithm()
for _, opt := range opts {
if err := opt(a); err != nil {
return nil, err
}
}
return a, nil
}
// WithLevel compression level.
// Supported by gzip, zlib.
func WithLevel(level Level) Option {
return func(a Algorithm) error {
return a.SetLevel(level)
}
}
// WithLitWidth the number of bit's to use for literal codes.
// Supported by lzw.
func WithLitWidth(width int) Option {
return func(a Algorithm) error {
return a.SetLitWidth(width)
}
}
// WithEndian either MSB (most significant byte) or LSB (least significant byte).
// Supported by lzw.
func WithEndian(endian Endian) Option {
return func(a Algorithm) error {
return a.SetEndian(endian)
}
}
// Encode algorithm.
func Encode(a Algorithm, v []byte) ([]byte, error) {
var buf bytes.Buffer
e, err := a.NewEncoder(&buf)
if err != nil {
return nil, err
}
if _, err := e.Write(v); err != nil {
return nil, err
}
if err := e.Close(); err != nil {
return nil, err
}
return buf.Bytes(), nil
}
// Decode algorithm.
func Decode(a Algorithm, v []byte) ([]byte, error) {
d, err := a.NewDecoder(bytes.NewBuffer(v))
if err != nil {
return nil, err
}
var buf bytes.Buffer
if _, err := io.Copy(&buf, d); err != nil {
return nil, err
}
if err := d.Close(); err != nil {
return nil, err
}
return buf.Bytes(), nil
}