-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathencoding.go
109 lines (89 loc) · 2.17 KB
/
encoding.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
// Package embdr provides functions for encoding and decoding data in gz compressed base64 format.
package embdr
//go:generate go run ./cmd/embdr/main.go -p embdr -o template.go template.tmpl
import (
"bytes"
"compress/gzip"
"encoding/base64"
"fmt"
"io"
"io/ioutil"
"unicode/utf8"
)
// EncodeFiles encodes multiple files to map and uses filename as a key.
func EncodeFiles(filenames ...string) (map[string]string, error) {
output := make(map[string]string, len(filenames))
for _, filename := range filenames {
data, err := ioutil.ReadFile(filename)
if err != nil {
return nil, err
}
encoded, err := Encode(data)
if err != nil {
return nil, fmt.Errorf("encoding %s failed: %w", filename, err)
}
output[filename] = string(encoded)
}
return output, nil
}
func Encode(data []byte) ([]byte, error) {
if !utf8.Valid(data) {
return nil, fmt.Errorf("invalid utf8 input")
}
buf := &bytes.Buffer{}
enc := base64.NewEncoder(base64.StdEncoding, NewNLWriter(buf, 80))
w, err := gzip.NewWriterLevel(enc, gzip.BestCompression)
if err != nil {
return nil, fmt.Errorf("couldn't create encoder: %w", err)
}
if _, err := w.Write(data); err != nil {
return nil, err
}
if err := w.Close(); err != nil {
return nil, err
}
if err := enc.Close(); err != nil {
return nil, err
}
return buf.Bytes(), nil
}
func Decode(s string) ([]byte, error) {
r, err := gzip.NewReader(base64.NewDecoder(base64.StdEncoding, bytes.NewBufferString(s)))
if err != nil {
return nil, err
}
data, err := ioutil.ReadAll(r)
if err != nil {
return nil, err
}
if err := r.Close(); err != nil {
return nil, err
}
return data, nil
}
type NLWriter struct {
w io.Writer
buf *bytes.Buffer
lineLength int
c int
}
func NewNLWriter(w io.Writer, lineLength int) *NLWriter {
return &NLWriter{
w: w,
buf: bytes.NewBuffer(make([]byte, 0, lineLength)),
lineLength: lineLength,
}
}
func (w *NLWriter) Write(p []byte) (int, error) {
w.buf.Reset()
last := len(p) - 1
for i, b := range p {
_ = w.buf.WriteByte(b)
w.c++
if w.c == w.lineLength && i != last {
_ = w.buf.WriteByte('\n')
w.c = 0
}
}
return w.w.Write(w.buf.Bytes())
}