1
2
3
4
5
6 package base64
7
8 import (
9 "encoding/binary"
10 "io"
11 "strconv"
12 )
13
14
17
18
19
20
21
22
23 type Encoding struct {
24 encode [64]byte
25 decodeMap [256]byte
26 padChar rune
27 strict bool
28 }
29
30 const (
31 StdPadding rune = '='
32 NoPadding rune = -1
33 decodeMapInitialize = "" +
34 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
35 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
36 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
37 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
38 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
39 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
40 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
41 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
42 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
43 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
44 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
45 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
46 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
47 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
48 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
49 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
50 )
51
52 const encodeStd = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
53 const encodeURL = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
54
55
56
57
58
59
60 func NewEncoding(encoder string) *Encoding {
61 if len(encoder) != 64 {
62 panic("encoding alphabet is not 64-bytes long")
63 }
64 for i := 0; i < len(encoder); i++ {
65 if encoder[i] == '\n' || encoder[i] == '\r' {
66 panic("encoding alphabet contains newline character")
67 }
68 }
69
70 e := new(Encoding)
71 e.padChar = StdPadding
72 copy(e.encode[:], encoder)
73 copy(e.decodeMap[:], decodeMapInitialize)
74
75 for i := 0; i < len(encoder); i++ {
76 e.decodeMap[encoder[i]] = byte(i)
77 }
78 return e
79 }
80
81
82
83
84
85
86 func (enc Encoding) WithPadding(padding rune) *Encoding {
87 if padding == '\r' || padding == '\n' || padding > 0xff {
88 panic("invalid padding")
89 }
90
91 for i := 0; i < len(enc.encode); i++ {
92 if rune(enc.encode[i]) == padding {
93 panic("padding contained in alphabet")
94 }
95 }
96
97 enc.padChar = padding
98 return &enc
99 }
100
101
102
103
104
105
106
107 func (enc Encoding) Strict() *Encoding {
108 enc.strict = true
109 return &enc
110 }
111
112
113
114 var StdEncoding = NewEncoding(encodeStd)
115
116
117
118 var URLEncoding = NewEncoding(encodeURL)
119
120
121
122
123 var RawStdEncoding = StdEncoding.WithPadding(NoPadding)
124
125
126
127
128 var RawURLEncoding = URLEncoding.WithPadding(NoPadding)
129
130
133
134
135
136
137
138
139
140 func (enc *Encoding) Encode(dst, src []byte) {
141 if len(src) == 0 {
142 return
143 }
144
145
146
147 _ = enc.encode
148
149 di, si := 0, 0
150 n := (len(src) / 3) * 3
151 for si < n {
152
153 val := uint(src[si+0])<<16 | uint(src[si+1])<<8 | uint(src[si+2])
154
155 dst[di+0] = enc.encode[val>>18&0x3F]
156 dst[di+1] = enc.encode[val>>12&0x3F]
157 dst[di+2] = enc.encode[val>>6&0x3F]
158 dst[di+3] = enc.encode[val&0x3F]
159
160 si += 3
161 di += 4
162 }
163
164 remain := len(src) - si
165 if remain == 0 {
166 return
167 }
168
169 val := uint(src[si+0]) << 16
170 if remain == 2 {
171 val |= uint(src[si+1]) << 8
172 }
173
174 dst[di+0] = enc.encode[val>>18&0x3F]
175 dst[di+1] = enc.encode[val>>12&0x3F]
176
177 switch remain {
178 case 2:
179 dst[di+2] = enc.encode[val>>6&0x3F]
180 if enc.padChar != NoPadding {
181 dst[di+3] = byte(enc.padChar)
182 }
183 case 1:
184 if enc.padChar != NoPadding {
185 dst[di+2] = byte(enc.padChar)
186 dst[di+3] = byte(enc.padChar)
187 }
188 }
189 }
190
191
192 func (enc *Encoding) EncodeToString(src []byte) string {
193 buf := make([]byte, enc.EncodedLen(len(src)))
194 enc.Encode(buf, src)
195 return string(buf)
196 }
197
198 type encoder struct {
199 err error
200 enc *Encoding
201 w io.Writer
202 buf [3]byte
203 nbuf int
204 out [1024]byte
205 }
206
207 func (e *encoder) Write(p []byte) (n int, err error) {
208 if e.err != nil {
209 return 0, e.err
210 }
211
212
213 if e.nbuf > 0 {
214 var i int
215 for i = 0; i < len(p) && e.nbuf < 3; i++ {
216 e.buf[e.nbuf] = p[i]
217 e.nbuf++
218 }
219 n += i
220 p = p[i:]
221 if e.nbuf < 3 {
222 return
223 }
224 e.enc.Encode(e.out[:], e.buf[:])
225 if _, e.err = e.w.Write(e.out[:4]); e.err != nil {
226 return n, e.err
227 }
228 e.nbuf = 0
229 }
230
231
232 for len(p) >= 3 {
233 nn := len(e.out) / 4 * 3
234 if nn > len(p) {
235 nn = len(p)
236 nn -= nn % 3
237 }
238 e.enc.Encode(e.out[:], p[:nn])
239 if _, e.err = e.w.Write(e.out[0 : nn/3*4]); e.err != nil {
240 return n, e.err
241 }
242 n += nn
243 p = p[nn:]
244 }
245
246
247 copy(e.buf[:], p)
248 e.nbuf = len(p)
249 n += len(p)
250 return
251 }
252
253
254
255 func (e *encoder) Close() error {
256
257 if e.err == nil && e.nbuf > 0 {
258 e.enc.Encode(e.out[:], e.buf[:e.nbuf])
259 _, e.err = e.w.Write(e.out[:e.enc.EncodedLen(e.nbuf)])
260 e.nbuf = 0
261 }
262 return e.err
263 }
264
265
266
267
268
269
270 func NewEncoder(enc *Encoding, w io.Writer) io.WriteCloser {
271 return &encoder{enc: enc, w: w}
272 }
273
274
275
276 func (enc *Encoding) EncodedLen(n int) int {
277 if enc.padChar == NoPadding {
278 return (n*8 + 5) / 6
279 }
280 return (n + 2) / 3 * 4
281 }
282
283
286
287 type CorruptInputError int64
288
289 func (e CorruptInputError) Error() string {
290 return "illegal base64 data at input byte " + strconv.FormatInt(int64(e), 10)
291 }
292
293
294
295
296
297
298 func (enc *Encoding) decodeQuantum(dst, src []byte, si int) (nsi, n int, err error) {
299
300 var dbuf [4]byte
301 dlen := 4
302
303
304 _ = enc.decodeMap
305
306 for j := 0; j < len(dbuf); j++ {
307 if len(src) == si {
308 switch {
309 case j == 0:
310 return si, 0, nil
311 case j == 1, enc.padChar != NoPadding:
312 return si, 0, CorruptInputError(si - j)
313 }
314 dlen = j
315 break
316 }
317 in := src[si]
318 si++
319
320 out := enc.decodeMap[in]
321 if out != 0xff {
322 dbuf[j] = out
323 continue
324 }
325
326 if in == '\n' || in == '\r' {
327 j--
328 continue
329 }
330
331 if rune(in) != enc.padChar {
332 return si, 0, CorruptInputError(si - 1)
333 }
334
335
336 switch j {
337 case 0, 1:
338
339 return si, 0, CorruptInputError(si - 1)
340 case 2:
341
342
343 for si < len(src) && (src[si] == '\n' || src[si] == '\r') {
344 si++
345 }
346 if si == len(src) {
347
348 return si, 0, CorruptInputError(len(src))
349 }
350 if rune(src[si]) != enc.padChar {
351
352 return si, 0, CorruptInputError(si - 1)
353 }
354
355 si++
356 }
357
358
359 for si < len(src) && (src[si] == '\n' || src[si] == '\r') {
360 si++
361 }
362 if si < len(src) {
363
364 err = CorruptInputError(si)
365 }
366 dlen = j
367 break
368 }
369
370
371 val := uint(dbuf[0])<<18 | uint(dbuf[1])<<12 | uint(dbuf[2])<<6 | uint(dbuf[3])
372 dbuf[2], dbuf[1], dbuf[0] = byte(val>>0), byte(val>>8), byte(val>>16)
373 switch dlen {
374 case 4:
375 dst[2] = dbuf[2]
376 dbuf[2] = 0
377 fallthrough
378 case 3:
379 dst[1] = dbuf[1]
380 if enc.strict && dbuf[2] != 0 {
381 return si, 0, CorruptInputError(si - 1)
382 }
383 dbuf[1] = 0
384 fallthrough
385 case 2:
386 dst[0] = dbuf[0]
387 if enc.strict && (dbuf[1] != 0 || dbuf[2] != 0) {
388 return si, 0, CorruptInputError(si - 2)
389 }
390 }
391
392 return si, dlen - 1, err
393 }
394
395
396 func (enc *Encoding) DecodeString(s string) ([]byte, error) {
397 dbuf := make([]byte, enc.DecodedLen(len(s)))
398 n, err := enc.Decode(dbuf, []byte(s))
399 return dbuf[:n], err
400 }
401
402 type decoder struct {
403 err error
404 readErr error
405 enc *Encoding
406 r io.Reader
407 buf [1024]byte
408 nbuf int
409 out []byte
410 outbuf [1024 / 4 * 3]byte
411 }
412
413 func (d *decoder) Read(p []byte) (n int, err error) {
414
415 if len(d.out) > 0 {
416 n = copy(p, d.out)
417 d.out = d.out[n:]
418 return n, nil
419 }
420
421 if d.err != nil {
422 return 0, d.err
423 }
424
425
426
427
428 for d.nbuf < 4 && d.readErr == nil {
429 nn := len(p) / 3 * 4
430 if nn < 4 {
431 nn = 4
432 }
433 if nn > len(d.buf) {
434 nn = len(d.buf)
435 }
436 nn, d.readErr = d.r.Read(d.buf[d.nbuf:nn])
437 d.nbuf += nn
438 }
439
440 if d.nbuf < 4 {
441 if d.enc.padChar == NoPadding && d.nbuf > 0 {
442
443 var nw int
444 nw, d.err = d.enc.Decode(d.outbuf[:], d.buf[:d.nbuf])
445 d.nbuf = 0
446 d.out = d.outbuf[:nw]
447 n = copy(p, d.out)
448 d.out = d.out[n:]
449 if n > 0 || len(p) == 0 && len(d.out) > 0 {
450 return n, nil
451 }
452 if d.err != nil {
453 return 0, d.err
454 }
455 }
456 d.err = d.readErr
457 if d.err == io.EOF && d.nbuf > 0 {
458 d.err = io.ErrUnexpectedEOF
459 }
460 return 0, d.err
461 }
462
463
464 nr := d.nbuf / 4 * 4
465 nw := d.nbuf / 4 * 3
466 if nw > len(p) {
467 nw, d.err = d.enc.Decode(d.outbuf[:], d.buf[:nr])
468 d.out = d.outbuf[:nw]
469 n = copy(p, d.out)
470 d.out = d.out[n:]
471 } else {
472 n, d.err = d.enc.Decode(p, d.buf[:nr])
473 }
474 d.nbuf -= nr
475 copy(d.buf[:d.nbuf], d.buf[nr:])
476 return n, d.err
477 }
478
479
480
481
482
483
484 func (enc *Encoding) Decode(dst, src []byte) (n int, err error) {
485 if len(src) == 0 {
486 return 0, nil
487 }
488
489
490
491
492 _ = enc.decodeMap
493
494 si := 0
495 for strconv.IntSize >= 64 && len(src)-si >= 8 && len(dst)-n >= 8 {
496 src2 := src[si : si+8]
497 if dn, ok := assemble64(
498 enc.decodeMap[src2[0]],
499 enc.decodeMap[src2[1]],
500 enc.decodeMap[src2[2]],
501 enc.decodeMap[src2[3]],
502 enc.decodeMap[src2[4]],
503 enc.decodeMap[src2[5]],
504 enc.decodeMap[src2[6]],
505 enc.decodeMap[src2[7]],
506 ); ok {
507 binary.BigEndian.PutUint64(dst[n:], dn)
508 n += 6
509 si += 8
510 } else {
511 var ninc int
512 si, ninc, err = enc.decodeQuantum(dst[n:], src, si)
513 n += ninc
514 if err != nil {
515 return n, err
516 }
517 }
518 }
519
520 for len(src)-si >= 4 && len(dst)-n >= 4 {
521 src2 := src[si : si+4]
522 if dn, ok := assemble32(
523 enc.decodeMap[src2[0]],
524 enc.decodeMap[src2[1]],
525 enc.decodeMap[src2[2]],
526 enc.decodeMap[src2[3]],
527 ); ok {
528 binary.BigEndian.PutUint32(dst[n:], dn)
529 n += 3
530 si += 4
531 } else {
532 var ninc int
533 si, ninc, err = enc.decodeQuantum(dst[n:], src, si)
534 n += ninc
535 if err != nil {
536 return n, err
537 }
538 }
539 }
540
541 for si < len(src) {
542 var ninc int
543 si, ninc, err = enc.decodeQuantum(dst[n:], src, si)
544 n += ninc
545 if err != nil {
546 return n, err
547 }
548 }
549 return n, err
550 }
551
552
553
554
555 func assemble32(n1, n2, n3, n4 byte) (dn uint32, ok bool) {
556
557
558 if n1|n2|n3|n4 == 0xff {
559 return 0, false
560 }
561 return uint32(n1)<<26 |
562 uint32(n2)<<20 |
563 uint32(n3)<<14 |
564 uint32(n4)<<8,
565 true
566 }
567
568
569
570
571 func assemble64(n1, n2, n3, n4, n5, n6, n7, n8 byte) (dn uint64, ok bool) {
572
573
574 if n1|n2|n3|n4|n5|n6|n7|n8 == 0xff {
575 return 0, false
576 }
577 return uint64(n1)<<58 |
578 uint64(n2)<<52 |
579 uint64(n3)<<46 |
580 uint64(n4)<<40 |
581 uint64(n5)<<34 |
582 uint64(n6)<<28 |
583 uint64(n7)<<22 |
584 uint64(n8)<<16,
585 true
586 }
587
588 type newlineFilteringReader struct {
589 wrapped io.Reader
590 }
591
592 func (r *newlineFilteringReader) Read(p []byte) (int, error) {
593 n, err := r.wrapped.Read(p)
594 for n > 0 {
595 offset := 0
596 for i, b := range p[:n] {
597 if b != '\r' && b != '\n' {
598 if i != offset {
599 p[offset] = b
600 }
601 offset++
602 }
603 }
604 if offset > 0 {
605 return offset, err
606 }
607
608 n, err = r.wrapped.Read(p)
609 }
610 return n, err
611 }
612
613
614 func NewDecoder(enc *Encoding, r io.Reader) io.Reader {
615 return &decoder{enc: enc, r: &newlineFilteringReader{r}}
616 }
617
618
619
620 func (enc *Encoding) DecodedLen(n int) int {
621 if enc.padChar == NoPadding {
622
623 return n * 6 / 8
624 }
625
626 return n / 4 * 3
627 }
628
View as plain text