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 }