github.com/sandwich-go/boost@v1.3.29/xencoding/compressor/compressor.go (about)

     1  package compressor
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"github.com/sandwich-go/boost/xcompress"
     7  	"github.com/sandwich-go/boost/xencoding"
     8  	"github.com/sandwich-go/boost/xpanic"
     9  )
    10  
    11  var (
    12  	errCodecMarshalParam   = errors.New("compressor codec marshal must be []byte parameter")
    13  	errCodecUnmarshalParam = errors.New("compressor codec unmarshal must be *[]byte parameter")
    14  	errCodecNoFound        = errors.New("compressor codec not found")
    15  )
    16  
    17  const (
    18  	// NoneCodecName 无压缩效果名称,可以通过 encoding2.GetCodec(NoneCodecName) 获取对应的 Codec
    19  	NoneCodecName = "none_compressor"
    20  	// GZIPCodecName gzip 压缩名称,可以通过 encoding2.GetCodec(GZIPCodecName) 获取对应的 Codec
    21  	GZIPCodecName = "gzip_compressor"
    22  	// SnappyCodecName snappy 压缩名称,可以通过 encoding2.GetCodec(SnappyCodecName) 获取对应的 Codec
    23  	SnappyCodecName = "snappy_compressor"
    24  )
    25  
    26  var (
    27  	// NoneCodec 无压缩效果
    28  	NoneCodec = noneCodec{newBaseCodec(xcompress.WithType(xcompress.Dummy))}
    29  	// GZIPCodec gzip 压缩,使用 compressor.DefaultCompression 等级
    30  	GZIPCodec = gzipCodec{newBaseCodec(xcompress.WithType(xcompress.GZIP), xcompress.WithLevel(xcompress.DefaultCompression))}
    31  	// SnappyCodec snappy 压缩
    32  	SnappyCodec = snappyCodec{newBaseCodec(xcompress.WithType(xcompress.Snappy))}
    33  )
    34  
    35  var codecs = map[Type]xencoding.Codec{
    36  	NoneType:   NoneCodec,
    37  	GZIPType:   GZIPCodec,
    38  	SnappyType: SnappyCodec,
    39  }
    40  
    41  func init() {
    42  	for _, v := range codecs {
    43  		xencoding.RegisterCodec(v)
    44  	}
    45  }
    46  
    47  // Register 注册自定义的解压缩 Codec ,该方法非协程安全
    48  func Register(t Type, codec xencoding.Codec) {
    49  	_, exists := codecs[t]
    50  	xpanic.WhenTrue(exists, "register called twice for codec, %d", t)
    51  	codecs[t] = codec
    52  	xencoding.RegisterCodec(codec)
    53  }
    54  
    55  type baseCodec struct {
    56  	xcompress.Compressor
    57  }
    58  
    59  func newBaseCodec(opts ...xcompress.Option) baseCodec {
    60  	return baseCodec{Compressor: xcompress.MustNew(opts...)}
    61  }
    62  
    63  func (c baseCodec) Marshal(_ context.Context, v interface{}) ([]byte, error) {
    64  	if data, ok := v.([]byte); !ok {
    65  		return nil, errCodecMarshalParam
    66  	} else {
    67  		return c.Compressor.Flat(data)
    68  	}
    69  }
    70  
    71  func (c baseCodec) Unmarshal(_ context.Context, bytes []byte, v interface{}) error {
    72  	v1, ok := v.(*[]byte)
    73  	if !ok {
    74  		return errCodecUnmarshalParam
    75  	}
    76  	data, err := c.Compressor.Inflate(bytes)
    77  	if err != nil {
    78  		return err
    79  	}
    80  	*v1 = data
    81  	return nil
    82  }
    83  
    84  type (
    85  	noneCodec   struct{ baseCodec }
    86  	gzipCodec   struct{ baseCodec }
    87  	snappyCodec struct{ baseCodec }
    88  )
    89  
    90  func (c noneCodec) Name() string   { return NoneCodecName }
    91  func (c gzipCodec) Name() string   { return GZIPCodecName }
    92  func (c snappyCodec) Name() string { return SnappyCodecName }
    93  
    94  type codec struct {
    95  	_type Type
    96  }
    97  
    98  // NewCodec 通过压缩类型创建压缩 Codec
    99  func NewCodec(compressType Type) xencoding.Codec {
   100  	return codec{_type: compressType}
   101  }
   102  
   103  // Name 返回 Codec 名
   104  func (c codec) Name() string { return "compressor" }
   105  
   106  // Marshal 编码
   107  func (c codec) Marshal(ctx context.Context, v interface{}) ([]byte, error) {
   108  	cc, ok1 := codecs[c._type]
   109  	if !ok1 {
   110  		return nil, errCodecNoFound
   111  	}
   112  	return cc.Marshal(ctx, v)
   113  }
   114  
   115  // Unmarshal 解码
   116  func (c codec) Unmarshal(ctx context.Context, bytes []byte, v interface{}) error {
   117  	cc, ok1 := codecs[c._type]
   118  	if !ok1 {
   119  		return errCodecNoFound
   120  	}
   121  	return cc.Unmarshal(ctx, bytes, v)
   122  }