@@ -16,6 +16,7 @@ import (
16
16
* Encodings
17
17
*/
18
18
19
+ type MappingFunc func (in uint ) byte
19
20
// An Encoding is a radix 64 encoding/decoding scheme, defined by a
20
21
// 64-character alphabet. The most common encoding is the "base64"
21
22
// encoding defined in RFC 4648 and used in MIME (RFC 2045) and PEM
@@ -26,6 +27,8 @@ type Encoding struct {
26
27
decodeMap [256 ]uint8 // mapping of symbol byte value to symbol index
27
28
padChar rune
28
29
strict bool
30
+ encodeMapFunc MappingFunc // optional mapping function to replace table look-ups when encoding
31
+ decodeMapFunc MappingFunc // optional mapping function to replace table look-ups when decoding
29
32
}
30
33
31
34
const (
@@ -83,6 +86,10 @@ func NewEncoding(encoder string) *Encoding {
83
86
}
84
87
e.decodeMap [encoder [i ]] = uint8 (i )
85
88
}
89
+ var encodeFunc = e .encodeMapDefault
90
+ e .encodeMapFunc = encodeFunc
91
+ var decodeFunc = e .decodeMapDefault
92
+ e .decodeMapFunc = decodeFunc
86
93
return e
87
94
}
88
95
@@ -104,6 +111,17 @@ func (enc Encoding) WithPadding(padding rune) *Encoding {
104
111
return & enc
105
112
}
106
113
114
+ // WithDecodeMappingFunc sets the value fo encodeMapFunc
115
+ func (enc Encoding ) WithDecodeMappingFunc (f MappingFunc ) * Encoding {
116
+ enc .decodeMapFunc = f
117
+ return & enc
118
+ }
119
+ // WithEncodeMappingFunc sets the value fo encodeMapFunc
120
+ func (enc Encoding ) WithEncodeMappingFunc (f MappingFunc ) * Encoding {
121
+ enc .encodeMapFunc = f
122
+ return & enc
123
+ }
124
+
107
125
// Strict creates a new encoding identical to enc except with
108
126
// strict decoding enabled. In this mode, the decoder requires that
109
127
// trailing padding bits are zero, as described in RFC 4648 section 3.5.
@@ -116,11 +134,15 @@ func (enc Encoding) Strict() *Encoding {
116
134
}
117
135
118
136
// StdEncoding is the standard base64 encoding, as defined in RFC 4648.
119
- var StdEncoding = NewEncoding ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" )
137
+ var StdEncoding = NewEncoding ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" ).
138
+ WithEncodeMappingFunc (StandardBase64Encode ).
139
+ WithDecodeMappingFunc (StandardBase64Decode )
120
140
121
141
// URLEncoding is the alternate base64 encoding defined in RFC 4648.
122
142
// It is typically used in URLs and file names.
123
- var URLEncoding = NewEncoding ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_" )
143
+ var URLEncoding = NewEncoding ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_" ).
144
+ WithEncodeMappingFunc (UrlSafeBase64Encode ).
145
+ WithDecodeMappingFunc (UrlSafeBase64Decode )
124
146
125
147
// RawStdEncoding is the standard raw, unpadded base64 encoding,
126
148
// as defined in RFC 4648 section 3.2.
@@ -157,10 +179,10 @@ func (enc *Encoding) Encode(dst, src []byte) {
157
179
// Convert 3x 8bit source bytes into 4 bytes
158
180
val := uint (src [si + 0 ])<< 16 | uint (src [si + 1 ])<< 8 | uint (src [si + 2 ])
159
181
160
- dst [di + 0 ] = enc .encode [ val >> 18 & 0x3F ]
161
- dst [di + 1 ] = enc .encode [ val >> 12 & 0x3F ]
162
- dst [di + 2 ] = enc .encode [ val >> 6 & 0x3F ]
163
- dst [di + 3 ] = enc .encode [ val & 0x3F ]
182
+ dst [di + 0 ] = enc .encodeMapFunc ( val >> 18 & 0x3F )
183
+ dst [di + 1 ] = enc .encodeMapFunc ( val >> 12 & 0x3F )
184
+ dst [di + 2 ] = enc .encodeMapFunc ( val >> 6 & 0x3F )
185
+ dst [di + 3 ] = enc .encodeMapFunc ( val & 0x3F )
164
186
165
187
si += 3
166
188
di += 4
@@ -176,8 +198,8 @@ func (enc *Encoding) Encode(dst, src []byte) {
176
198
val |= uint (src [si + 1 ]) << 8
177
199
}
178
200
179
- dst [di + 0 ] = enc .encode [ val >> 18 & 0x3F ]
180
- dst [di + 1 ] = enc .encode [ val >> 12 & 0x3F ]
201
+ dst [di + 0 ] = enc .encodeMapFunc ( val >> 18 & 0x3F )
202
+ dst [di + 1 ] = enc .encodeMapFunc ( val >> 12 & 0x3F )
181
203
182
204
switch remain {
183
205
case 2 :
@@ -330,8 +352,7 @@ func (enc *Encoding) decodeQuantum(dst, src []byte, si int) (nsi, n int, err err
330
352
}
331
353
in := src [si ]
332
354
si ++
333
-
334
- out := enc .decodeMap [in ]
355
+ out := enc .decodeMapFunc (uint (in ))
335
356
if out != 0xff {
336
357
dbuf [j ] = out
337
358
continue
@@ -529,14 +550,14 @@ func (enc *Encoding) Decode(dst, src []byte) (n int, err error) {
529
550
for strconv .IntSize >= 64 && len (src )- si >= 8 && len (dst )- n >= 8 {
530
551
src2 := src [si : si + 8 ]
531
552
if dn , ok := assemble64 (
532
- enc .decodeMap [ src2 [0 ]] ,
533
- enc .decodeMap [ src2 [1 ]] ,
534
- enc .decodeMap [ src2 [2 ]] ,
535
- enc .decodeMap [ src2 [3 ]] ,
536
- enc .decodeMap [ src2 [4 ]] ,
537
- enc .decodeMap [ src2 [5 ]] ,
538
- enc .decodeMap [ src2 [6 ]] ,
539
- enc .decodeMap [ src2 [7 ]] ,
553
+ enc .decodeMapFunc ( uint ( src2 [0 ])) ,
554
+ enc .decodeMapFunc ( uint ( src2 [1 ])) ,
555
+ enc .decodeMapFunc ( uint ( src2 [2 ])) ,
556
+ enc .decodeMapFunc ( uint ( src2 [3 ])) ,
557
+ enc .decodeMapFunc ( uint ( src2 [4 ])) ,
558
+ enc .decodeMapFunc ( uint ( src2 [5 ])) ,
559
+ enc .decodeMapFunc ( uint ( src2 [6 ])) ,
560
+ enc .decodeMapFunc ( uint ( src2 [7 ])) ,
540
561
); ok {
541
562
byteorder .BEPutUint64 (dst [n :], dn )
542
563
n += 6
@@ -554,10 +575,10 @@ func (enc *Encoding) Decode(dst, src []byte) (n int, err error) {
554
575
for len (src )- si >= 4 && len (dst )- n >= 4 {
555
576
src2 := src [si : si + 4 ]
556
577
if dn , ok := assemble32 (
557
- enc .decodeMap [ src2 [0 ]] ,
558
- enc .decodeMap [ src2 [1 ]] ,
559
- enc .decodeMap [ src2 [2 ]] ,
560
- enc .decodeMap [ src2 [3 ]] ,
578
+ enc .decodeMapFunc ( uint ( src2 [0 ])) ,
579
+ enc .decodeMapFunc ( uint ( src2 [1 ])) ,
580
+ enc .decodeMapFunc ( uint ( src2 [2 ])) ,
581
+ enc .decodeMapFunc ( uint ( src2 [3 ])) ,
561
582
); ok {
562
583
byteorder .BEPutUint32 (dst [n :], dn )
563
584
n += 3
0 commit comments