package ocf
import (
"bytes"
"compress/flate"
"encoding/binary"
"errors"
"fmt"
"hash/crc32"
"io"
"github.com/golang/snappy"
"github.com/klauspost/compress/zstd"
)
type CodecName string
const (
Null CodecName = "null"
Deflate CodecName = "deflate"
Snappy CodecName = "snappy"
ZStandard CodecName = "zstandard"
)
type codecOptions struct {
DeflateCompressionLevel int
ZStandardOptions zstdOptions
}
type zstdOptions struct {
EOptions []zstd .EOption
DOptions []zstd .DOption
}
func resolveCodec(name CodecName , codecOpts codecOptions ) (Codec , error ) {
switch name {
case Null , "" :
return &NullCodec {}, nil
case Deflate :
return &DeflateCodec {compLvl : codecOpts .DeflateCompressionLevel }, nil
case Snappy :
return &SnappyCodec {}, nil
case ZStandard :
return newZStandardCodec (codecOpts .ZStandardOptions ), nil
default :
return nil , fmt .Errorf ("unknown codec %s" , name )
}
}
type Codec interface {
Decode ([]byte ) ([]byte , error )
Encode ([]byte ) []byte
}
type NullCodec struct {}
func (*NullCodec ) Decode (b []byte ) ([]byte , error ) {
return b , nil
}
func (*NullCodec ) Encode (b []byte ) []byte {
return b
}
type DeflateCodec struct {
compLvl int
}
func (c *DeflateCodec ) Decode (b []byte ) ([]byte , error ) {
r := flate .NewReader (bytes .NewBuffer (b ))
data , err := io .ReadAll (r )
if err != nil {
_ = r .Close ()
return nil , err
}
_ = r .Close ()
return data , nil
}
func (c *DeflateCodec ) Encode (b []byte ) []byte {
data := bytes .NewBuffer (make ([]byte , 0 , len (b )))
w , _ := flate .NewWriter (data , c .compLvl )
_, _ = w .Write (b )
_ = w .Close ()
return data .Bytes ()
}
type SnappyCodec struct {}
func (*SnappyCodec ) Decode (b []byte ) ([]byte , error ) {
l := len (b )
if l < 5 {
return nil , errors .New ("block does not contain snappy checksum" )
}
dst , err := snappy .Decode (nil , b [:l -4 ])
if err != nil {
return nil , err
}
crc := binary .BigEndian .Uint32 (b [l -4 :])
if crc32 .ChecksumIEEE (dst ) != crc {
return nil , errors .New ("snappy checksum mismatch" )
}
return dst , nil
}
func (*SnappyCodec ) Encode (b []byte ) []byte {
dst := snappy .Encode (nil , b )
dst = append (dst , 0 , 0 , 0 , 0 )
binary .BigEndian .PutUint32 (dst [len (dst )-4 :], crc32 .ChecksumIEEE (b ))
return dst
}
type ZStandardCodec struct {
decoder *zstd .Decoder
encoder *zstd .Encoder
}
func newZStandardCodec(opts zstdOptions ) *ZStandardCodec {
decoder , _ := zstd .NewReader (nil , opts .DOptions ...)
encoder , _ := zstd .NewWriter (nil , opts .EOptions ...)
return &ZStandardCodec {
decoder : decoder ,
encoder : encoder ,
}
}
func (zstdCodec *ZStandardCodec ) Decode (b []byte ) ([]byte , error ) {
defer func () { _ = zstdCodec .decoder .Reset (nil ) }()
return zstdCodec .decoder .DecodeAll (b , nil )
}
func (zstdCodec *ZStandardCodec ) Encode (b []byte ) []byte {
defer zstdCodec .encoder .Reset (nil )
return zstdCodec .encoder .EncodeAll (b , nil )
}
The pages are generated with Golds v0.8.2 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .