github.com/cristalhq/base64@v0.1.2/base64.go (about) 1 // based on https://github.com/powturbo/Turbo-Base64 2 package base64 3 4 import ( 5 "errors" 6 "unsafe" 7 ) 8 9 var ErrWrongData = errors.New("wrong base64 data") 10 11 type Encoding struct { 12 lutSe [64]byte 13 lutXe [4096]uint32 14 lutXd0 [256]uint32 15 lutXd1 [256]uint32 16 lutXd2 [256]uint32 17 lutXd3 [256]uint32 18 pad bool 19 } 20 21 func (e *Encoding) EncodedLen(n int) int { 22 if !e.pad { 23 return (n*8 + 5) / 6 24 } 25 return (n + 2) / 3 * 4 26 } 27 28 func (e *Encoding) Encode(dst []byte, src []byte) { 29 if len(src) == 0 { 30 return 31 } 32 e.encode(dst, src, uintptr(e.EncodedLen(len(src)))) 33 } 34 35 func (e *Encoding) EncodeToBytes(src []byte) []byte { 36 if len(src) == 0 { 37 return []byte{} 38 } 39 length := e.EncodedLen(len(src)) 40 result := make([]byte, length) 41 e.encode(result, src, uintptr(length)) 42 return result 43 } 44 45 func (e *Encoding) EncodeToString(src []byte) string { 46 return b2s(e.EncodeToBytes(src)) 47 } 48 49 func (e *Encoding) EncodeString(src string) []byte { 50 return e.EncodeToBytes(s2b(src)) 51 } 52 53 func (e *Encoding) EncodeStringToString(src string) string { 54 return b2s(e.EncodeToBytes(s2b(src))) 55 } 56 57 func (e *Encoding) DecodedLen(n int) int { 58 sf := 0 59 if n > 4 { 60 sf++ 61 } 62 if !e.pad { 63 return n*6/8 + sf 64 } 65 return n/4*3 + sf 66 } 67 68 func (e *Encoding) Decode(dst []byte, src []byte) (int, error) { 69 if len(src) == 0 { 70 return 0, nil 71 } 72 n := e.decode(dst, src) 73 if n == 0 { 74 return 0, ErrWrongData 75 } 76 return n, nil 77 } 78 79 func (e *Encoding) DecodeToBytes(src []byte) ([]byte, error) { 80 if len(src) == 0 { 81 return []byte{}, nil 82 } 83 length := e.DecodedLen(len(src)) 84 if length == 0 { 85 return nil, ErrWrongData 86 } 87 result := make([]byte, length) 88 n := e.decode(result, src) 89 if n == 0 { 90 return nil, ErrWrongData 91 } 92 (*sliceHeader)(unsafe.Pointer(&result)).len = n 93 return result, nil 94 } 95 96 func (e *Encoding) DecodeToString(src []byte) (string, error) { 97 result, err := e.DecodeToBytes(src) 98 if err != nil { 99 return "", err 100 } 101 return b2s(result), nil 102 } 103 104 func (e *Encoding) DecodeString(src string) ([]byte, error) { 105 return e.DecodeToBytes(s2b(src)) 106 } 107 108 func (e *Encoding) DecodeStringToString(src string) (string, error) { 109 result, err := e.DecodeToBytes(s2b(src)) 110 if err != nil { 111 return "", err 112 } 113 return b2s(result), nil 114 } 115 116 func NewEncoding(lutSe [64]byte, pad bool) *Encoding { 117 lutXe, lutXd0, lutXd1, lutXd2, lutXd3 := makeLuts(lutSe) 118 return &Encoding{ 119 lutSe: lutSe, 120 lutXe: lutXe, 121 lutXd0: lutXd0, 122 lutXd1: lutXd1, 123 lutXd2: lutXd2, 124 lutXd3: lutXd3, 125 pad: pad, 126 } 127 } 128 129 var ( 130 StdEncoding = NewEncoding(stdLutSe, true) 131 RawStdEncoding = NewEncoding(stdLutSe, false) 132 URLEncoding = NewEncoding(urlLutSe, true) 133 RawURLEncoding = NewEncoding(urlLutSe, false) 134 )