github.com/wfusion/gofusion@v1.1.14/common/utils/encode/stream.go (about) 1 package encode 2 3 import ( 4 "encoding/base32" 5 "encoding/base64" 6 "encoding/hex" 7 "errors" 8 "io" 9 10 "github.com/wfusion/gofusion/common/utils" 11 "github.com/wfusion/gofusion/common/utils/cipher" 12 "github.com/wfusion/gofusion/common/utils/compress" 13 ) 14 15 func NewCodecStream(opts ...utils.OptionExtender) Streamable { 16 encodeOrder := make([]EncodedType, 0, len(opts)) 17 for _, opt := range opts { 18 if encType := parseEncodedType(opt); encType.IsValid() { 19 encodeOrder = append(encodeOrder, encType) 20 } 21 } 22 if len(encodeOrder) == 0 { 23 panic(ErrEncodeMethodNotFound) 24 } 25 return &codecStream{ 26 o: utils.ApplyOptions[option](opts...), 27 encodeOrder: encodeOrder, 28 } 29 } 30 31 type codecStream struct { 32 o *option 33 encodeOrder []EncodedType 34 } 35 36 func (w *codecStream) Encode(dst io.Writer, src io.Reader) (n int64, err error) { 37 for i := len(w.encodeOrder) - 1; i >= 0; i-- { 38 switch w.encodeOrder[i] { 39 case EncodedTypeCompress: 40 dst = compress.NewEncFunc(w.o.compressAlgo)(dst) 41 case EncodedTypeCipher: 42 dst = cipher.NewEncFunc(w.o.cipherAlgo, w.o.cipherMode, w.o.key, w.o.iv)(dst) 43 case EncodedTypeEncode: 44 dst = NewWriter(w.o.printableAlgo, dst) 45 } 46 } 47 48 buf, cb := utils.BytesPool.Get(defaultBufferSize) 49 defer cb() 50 51 defer utils.CloseAnyway(dst) 52 n, err = io.CopyBuffer(dst, src, buf) 53 if errors.Is(err, io.ErrUnexpectedEOF) || errors.Is(err, io.EOF) { 54 err = nil 55 } 56 return 57 } 58 59 func (w *codecStream) Decode(dst io.Writer, src io.Reader) (n int64, err error) { 60 for i := len(w.encodeOrder) - 1; i >= 0; i-- { 61 switch w.encodeOrder[i] { 62 case EncodedTypeCompress: 63 src = compress.NewDecFunc(w.o.compressAlgo)(src) 64 case EncodedTypeCipher: 65 src = cipher.NewDecFunc(w.o.cipherAlgo, w.o.cipherMode, w.o.key, w.o.iv)(src) 66 case EncodedTypeEncode: 67 src = NewReader(w.o.printableAlgo, src) 68 } 69 } 70 71 buf, cb := utils.BytesPool.Get(defaultBufferSize) 72 defer cb() 73 defer utils.CloseAnyway(src) 74 n, err = io.CopyBuffer(dst, src, buf) 75 if errors.Is(err, io.ErrUnexpectedEOF) || errors.Is(err, io.EOF) { 76 err = nil 77 } 78 return 79 } 80 81 func NewWriter(algo Algorithm, w io.Writer) io.Writer { 82 switch algo { 83 case AlgorithmHex: 84 return newEncoder(hex.NewEncoder(w), w) 85 case AlgorithmBase32Std: 86 return newEncoder(base32.NewEncoder(base32.StdEncoding, w), w) 87 case AlgorithmBase32Hex: 88 return newEncoder(base32.NewEncoder(base32.HexEncoding, w), w) 89 case AlgorithmBase64Std: 90 return newEncoder(base64.NewEncoder(base64.StdEncoding, w), w) 91 case AlgorithmBase64URL: 92 return newEncoder(base64.NewEncoder(base64.URLEncoding, w), w) 93 case AlgorithmBase64RawStd: 94 return newEncoder(base64.NewEncoder(base64.RawStdEncoding, w), w) 95 case AlgorithmBase64RawURL: 96 return newEncoder(base64.NewEncoder(base64.RawURLEncoding, w), w) 97 default: 98 panic(ErrUnknownAlgorithm) 99 } 100 } 101 102 func NewEncodeFunc(algo Algorithm) func([]byte) ([]byte, error) { 103 var ( 104 encodeFunc func(src, dst []byte) 105 encodedLenFunc func(int) int 106 ) 107 switch algo { 108 case AlgorithmHex: 109 encodeFunc = func(src, dst []byte) { hex.Encode(src, dst) } 110 encodedLenFunc = hex.EncodedLen 111 case AlgorithmBase32Std: 112 encodeFunc = base32.StdEncoding.Encode 113 encodedLenFunc = base32.StdEncoding.EncodedLen 114 case AlgorithmBase32Hex: 115 encodeFunc = base32.HexEncoding.Encode 116 encodedLenFunc = base32.HexEncoding.EncodedLen 117 case AlgorithmBase64Std: 118 encodeFunc = base64.StdEncoding.Encode 119 encodedLenFunc = base64.StdEncoding.EncodedLen 120 case AlgorithmBase64URL: 121 encodeFunc = base64.URLEncoding.Encode 122 encodedLenFunc = base64.URLEncoding.EncodedLen 123 case AlgorithmBase64RawStd: 124 encodeFunc = base64.RawStdEncoding.Encode 125 encodedLenFunc = base64.RawStdEncoding.EncodedLen 126 case AlgorithmBase64RawURL: 127 encodeFunc = base64.RawURLEncoding.Encode 128 encodedLenFunc = base64.RawURLEncoding.EncodedLen 129 default: 130 panic(ErrUnknownAlgorithm) 131 } 132 133 return func(src []byte) (dst []byte, err error) { 134 dst = make([]byte, encodedLenFunc(len(src))) 135 encodeFunc(dst, src) 136 return 137 } 138 } 139 140 func NewReader(algo Algorithm, r io.Reader) io.Reader { 141 switch algo { 142 case AlgorithmHex: 143 return newDecoder(hex.NewDecoder(r), r) 144 case AlgorithmBase32Std: 145 return newDecoder(base32.NewDecoder(base32.StdEncoding, r), r) 146 case AlgorithmBase32Hex: 147 return newDecoder(base32.NewDecoder(base32.HexEncoding, r), r) 148 case AlgorithmBase64Std: 149 return newDecoder(base64.NewDecoder(base64.StdEncoding, r), r) 150 case AlgorithmBase64URL: 151 return newDecoder(base64.NewDecoder(base64.URLEncoding, r), r) 152 case AlgorithmBase64RawStd: 153 return newDecoder(base64.NewDecoder(base64.RawStdEncoding, r), r) 154 case AlgorithmBase64RawURL: 155 return newDecoder(base64.NewDecoder(base64.RawURLEncoding, r), r) 156 default: 157 panic(ErrUnknownAlgorithm) 158 } 159 return nil 160 } 161 162 func NewDecodeFunc(algo Algorithm) func([]byte) ([]byte, error) { 163 var ( 164 decodeFunc func(src, dst []byte) (int, error) 165 decodedLenFunc func(int) int 166 ) 167 switch algo { 168 case AlgorithmHex: 169 decodeFunc = hex.Decode 170 decodedLenFunc = hex.DecodedLen 171 case AlgorithmBase32Std: 172 decodeFunc = base32.StdEncoding.Decode 173 decodedLenFunc = base32.StdEncoding.DecodedLen 174 case AlgorithmBase32Hex: 175 decodeFunc = base32.HexEncoding.Decode 176 decodedLenFunc = base32.HexEncoding.DecodedLen 177 case AlgorithmBase64Std: 178 decodeFunc = base64.StdEncoding.Decode 179 decodedLenFunc = base64.StdEncoding.DecodedLen 180 case AlgorithmBase64URL: 181 decodeFunc = base64.URLEncoding.Decode 182 decodedLenFunc = base64.URLEncoding.DecodedLen 183 case AlgorithmBase64RawStd: 184 decodeFunc = base64.RawStdEncoding.Decode 185 decodedLenFunc = base64.RawStdEncoding.DecodedLen 186 case AlgorithmBase64RawURL: 187 decodeFunc = base64.RawURLEncoding.Decode 188 decodedLenFunc = base64.RawURLEncoding.DecodedLen 189 default: 190 panic(ErrUnknownAlgorithm) 191 } 192 193 return func(src []byte) (dst []byte, err error) { 194 dst = make([]byte, decodedLenFunc(len(src))) 195 n, err := decodeFunc(dst, src) 196 if err == nil { 197 dst = dst[:n] 198 } 199 return 200 } 201 } 202 203 type decoder struct { 204 dec, r io.Reader 205 } 206 207 func newDecoder(dec, r io.Reader) io.Reader { 208 return &decoder{dec: dec, r: r} 209 } 210 211 func (e *decoder) Read(p []byte) (n int, err error) { return e.dec.Read(p) } 212 func (e *decoder) Close() { utils.CloseAnyway(e.r); utils.CloseAnyway(e.dec) } 213 214 type encoder struct { 215 enc, w io.Writer 216 } 217 218 func newEncoder(enc, w io.Writer) io.Writer { 219 return &encoder{enc: enc, w: w} 220 } 221 222 func (e *encoder) Write(p []byte) (n int, err error) { return e.enc.Write(p) } 223 func (e *encoder) Close() { utils.CloseAnyway(e.enc); utils.CloseAnyway(e.w) }