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