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) }