base64x.go (4734B)
1 package base64x 2 3 import ( 4 `encoding/base64` 5 ) 6 7 // An Encoding is a radix 64 encoding/decoding scheme, defined by a 8 // 64-character alphabet. The most common encoding is the "base64" 9 // encoding defined in RFC 4648 and used in MIME (RFC 2045) and PEM 10 // (RFC 1421). RFC 4648 also defines an alternate encoding, which is 11 // the standard encoding with - and _ substituted for + and /. 12 type Encoding int 13 14 const ( 15 _MODE_URL = 1 << 0 16 _MODE_RAW = 1 << 1 17 _MODE_AVX2 = 1 << 2 18 _MODE_JSON = 1 << 3 19 ) 20 21 // StdEncoding is the standard base64 encoding, as defined in 22 // RFC 4648. 23 const StdEncoding Encoding = 0 24 25 // URLEncoding is the alternate base64 encoding defined in RFC 4648. 26 // It is typically used in URLs and file names. 27 const URLEncoding Encoding = _MODE_URL 28 29 // RawStdEncoding is the standard raw, unpadded base64 encoding, 30 // as defined in RFC 4648 section 3.2. 31 // 32 // This is the same as StdEncoding but omits padding characters. 33 const RawStdEncoding Encoding = _MODE_RAW 34 35 // RawURLEncoding is the unpadded alternate base64 encoding defined in RFC 4648. 36 // It is typically used in URLs and file names. 37 // 38 // This is the same as URLEncoding but omits padding characters. 39 const RawURLEncoding Encoding = _MODE_RAW | _MODE_URL 40 41 // JSONStdEncoding is the StdEncoding and encoded as JSON string as RFC 8259. 42 const JSONStdEncoding Encoding = _MODE_JSON; 43 44 var ( 45 archFlags = 0 46 ) 47 48 /** Encoder Functions **/ 49 50 // Encode encodes src using the specified encoding, writing 51 // EncodedLen(len(src)) bytes to out. 52 // 53 // The encoding pads the output to a multiple of 4 bytes, 54 // so Encode is not appropriate for use on individual blocks 55 // of a large data stream. 56 // 57 // If out is not large enough to contain the encoded result, 58 // it will panic. 59 func (self Encoding) Encode(out []byte, src []byte) { 60 if len(src) != 0 { 61 if buf := out[:0:len(out)]; self.EncodedLen(len(src)) <= len(out) { 62 self.EncodeUnsafe(&buf, src) 63 } else { 64 panic("encoder output buffer is too small") 65 } 66 } 67 } 68 69 // EncodeUnsafe behaves like Encode, except it does NOT check if 70 // out is large enough to contain the encoded result. 71 // 72 // It will also update the length of out. 73 func (self Encoding) EncodeUnsafe(out *[]byte, src []byte) { 74 __b64encode(out, &src, int(self) | archFlags) 75 } 76 77 // EncodeToString returns the base64 encoding of src. 78 func (self Encoding) EncodeToString(src []byte) string { 79 nbs := len(src) 80 ret := make([]byte, 0, self.EncodedLen(nbs)) 81 82 /* encode in native code */ 83 self.EncodeUnsafe(&ret, src) 84 return mem2str(ret) 85 } 86 87 // EncodedLen returns the length in bytes of the base64 encoding 88 // of an input buffer of length n. 89 func (self Encoding) EncodedLen(n int) int { 90 if (self & _MODE_RAW) == 0 { 91 return (n + 2) / 3 * 4 92 } else { 93 return (n * 8 + 5) / 6 94 } 95 } 96 97 /** Decoder Functions **/ 98 99 // Decode decodes src using the encoding enc. It writes at most 100 // DecodedLen(len(src)) bytes to out and returns the number of bytes 101 // written. If src contains invalid base64 data, it will return the 102 // number of bytes successfully written and base64.CorruptInputError. 103 // 104 // New line characters (\r and \n) are ignored. 105 // 106 // If out is not large enough to contain the encoded result, 107 // it will panic. 108 func (self Encoding) Decode(out []byte, src []byte) (int, error) { 109 if len(src) == 0 { 110 return 0, nil 111 } else if buf := out[:0:len(out)]; self.DecodedLen(len(src)) <= len(out) { 112 return self.DecodeUnsafe(&buf, src) 113 } else { 114 panic("decoder output buffer is too small") 115 } 116 } 117 118 // DecodeUnsafe behaves like Decode, except it does NOT check if 119 // out is large enough to contain the decoded result. 120 // 121 // It will also update the length of out. 122 func (self Encoding) DecodeUnsafe(out *[]byte, src []byte) (int, error) { 123 if n := __b64decode(out, mem2addr(src), len(src), int(self) | archFlags); n >= 0 { 124 return n, nil 125 } else { 126 return 0, base64.CorruptInputError(-n - 1) 127 } 128 } 129 130 // DecodeString returns the bytes represented by the base64 string s. 131 func (self Encoding) DecodeString(s string) ([]byte, error) { 132 src := str2mem(s) 133 ret := make([]byte, 0, self.DecodedLen(len(s))) 134 135 /* decode into the allocated buffer */ 136 if _, err := self.DecodeUnsafe(&ret, src); err != nil { 137 return nil, err 138 } else { 139 return ret, nil 140 } 141 } 142 143 // DecodedLen returns the maximum length in bytes of the decoded data 144 // corresponding to n bytes of base64-encoded data. 145 func (self Encoding) DecodedLen(n int) int { 146 if (self & _MODE_RAW) == 0 { 147 return n / 4 * 3 148 } else { 149 return n * 6 / 8 150 } 151 } 152 153 func init() { 154 if hasAVX2() { 155 archFlags = _MODE_AVX2 156 } 157 }