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