package zstd
import (
"encoding/binary"
"fmt"
"io"
"math"
"math/bits"
)
type frameHeader struct {
ContentSize uint64
WindowSize uint32
SingleSegment bool
Checksum bool
DictID uint32
}
const maxHeaderSize = 14
func (f frameHeader ) appendTo (dst []byte ) []byte {
dst = append (dst , frameMagic ...)
var fhd uint8
if f .Checksum {
fhd |= 1 << 2
}
if f .SingleSegment {
fhd |= 1 << 5
}
var dictIDContent []byte
if f .DictID > 0 {
var tmp [4 ]byte
if f .DictID < 256 {
fhd |= 1
tmp [0 ] = uint8 (f .DictID )
dictIDContent = tmp [:1 ]
} else if f .DictID < 1 <<16 {
fhd |= 2
binary .LittleEndian .PutUint16 (tmp [:2 ], uint16 (f .DictID ))
dictIDContent = tmp [:2 ]
} else {
fhd |= 3
binary .LittleEndian .PutUint32 (tmp [:4 ], f .DictID )
dictIDContent = tmp [:4 ]
}
}
var fcs uint8
if f .ContentSize >= 256 {
fcs ++
}
if f .ContentSize >= 65536 +256 {
fcs ++
}
if f .ContentSize >= 0xffffffff {
fcs ++
}
fhd |= fcs << 6
dst = append (dst , fhd )
if !f .SingleSegment {
const winLogMin = 10
windowLog := (bits .Len32 (f .WindowSize -1 ) - winLogMin ) << 3
dst = append (dst , uint8 (windowLog ))
}
if f .DictID > 0 {
dst = append (dst , dictIDContent ...)
}
switch fcs {
case 0 :
if f .SingleSegment {
dst = append (dst , uint8 (f .ContentSize ))
}
case 1 :
f .ContentSize -= 256
dst = append (dst , uint8 (f .ContentSize ), uint8 (f .ContentSize >>8 ))
case 2 :
dst = append (dst , uint8 (f .ContentSize ), uint8 (f .ContentSize >>8 ), uint8 (f .ContentSize >>16 ), uint8 (f .ContentSize >>24 ))
case 3 :
dst = append (dst , uint8 (f .ContentSize ), uint8 (f .ContentSize >>8 ), uint8 (f .ContentSize >>16 ), uint8 (f .ContentSize >>24 ),
uint8 (f .ContentSize >>32 ), uint8 (f .ContentSize >>40 ), uint8 (f .ContentSize >>48 ), uint8 (f .ContentSize >>56 ))
default :
panic ("invalid fcs" )
}
return dst
}
const skippableFrameHeader = 4 + 4
func calcSkippableFrame(written , wantMultiple int64 ) int {
if wantMultiple <= 0 {
panic ("wantMultiple <= 0" )
}
if written < 0 {
panic ("written < 0" )
}
leftOver := written % wantMultiple
if leftOver == 0 {
return 0
}
toAdd := wantMultiple - leftOver
for toAdd < skippableFrameHeader {
toAdd += wantMultiple
}
return int (toAdd )
}
func skippableFrame(dst []byte , total int , r io .Reader ) ([]byte , error ) {
if total == 0 {
return dst , nil
}
if total < skippableFrameHeader {
return dst , fmt .Errorf ("requested skippable frame (%d) < 8" , total )
}
if int64 (total ) > math .MaxUint32 {
return dst , fmt .Errorf ("requested skippable frame (%d) > max uint32" , total )
}
dst = append (dst , 0x50 , 0x2a , 0x4d , 0x18 )
f := uint32 (total - skippableFrameHeader )
dst = append (dst , uint8 (f ), uint8 (f >>8 ), uint8 (f >>16 ), uint8 (f >>24 ))
start := len (dst )
dst = append (dst , make ([]byte , f )...)
_ , err := io .ReadFull (r , dst [start :])
return dst , err
}
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 .