Support v29 blocks

This commit is contained in:
Sascha L. Teichmann 2024-01-06 01:40:03 +01:00
parent 827d73bed0
commit 8a344b5a6d
1 changed files with 198 additions and 81 deletions

View File

@ -92,6 +92,132 @@ type posBuf struct {
Pos int
}
type bigEndian struct {
data []byte
err error
}
func (be *bigEndian) Err() error {
return be.err
}
func (be *bigEndian) u8() uint8 {
if be.err != nil {
return 0
}
if len(be.data) >= 1 {
x := be.data[0]
be.data = be.data[1:]
return x
}
be.err = ErrBlockTruncated
return 0
}
func (be *bigEndian) u16() uint16 {
if be.err != nil {
return 0
}
if len(be.data) >= 2 {
x := binary.BigEndian.Uint16(be.data)
be.data = be.data[2:]
return x
}
be.err = ErrBlockTruncated
return 0
}
func (be *bigEndian) u32() uint32 {
if be.err != nil {
return 0
}
if len(be.data) >= 4 {
x := binary.BigEndian.Uint32(be.data)
be.data = be.data[4:]
return x
}
be.err = ErrBlockTruncated
return 0
}
func (be *bigEndian) str(l int) string {
if be.err != nil {
return ""
}
if len(be.data) >= l {
s := string(be.data[:l])
be.data = be.data[l:]
return s
}
be.err = ErrBlockTruncated
return ""
}
func decode29(data []byte, colors *Colors) (*DecodedBlock, error) {
dec, err := zstd.NewReader(nil)
if err != nil {
return nil, err
}
content, err := dec.DecodeAll(data, nil)
if err != nil {
return nil, err
}
be := bigEndian{data: content}
_ = be.u8() // flags
_ = be.u16() // lightning_complete
_ = be.u32() // timestamp
_ = be.u8() // name_id_mapping_version
airID, ignoreID := int32(-1), int32(-1)
indexMap := make(map[int32]int32)
transparent := false
numNameIDMappings := be.u16()
for i := uint16(0); i < numNameIDMappings; i++ {
id := int32(be.u16())
name := be.str(int(be.u16()))
switch name {
case "air":
airID = id
case "ignore":
ignoreID = id
default:
if index, found := colors.NameIndex[name]; found {
indexMap[id] = index
if !transparent && colors.IsTransparent(index) {
transparent = true
}
} else {
logMissing(name)
}
}
}
_ = be.u8() // content_width
_ = be.u8() // params_width
if err := be.Err(); err != nil {
return nil, err
}
mapContent := make([]byte, 2*4096)
if len(be.data) < len(mapContent) {
return nil, ErrBlockTruncated
}
copy(mapContent, be.data)
return &DecodedBlock{
Version: data[0],
Transparent: transparent,
MapContent: mapContent,
AirID: airID,
IgnoreID: ignoreID,
IndexMap: indexMap,
}, nil
}
func NewDecodedBlock(data []byte, colors *Colors) (db *DecodedBlock, err error) {
dataLen := len(data)
@ -101,20 +227,12 @@ func NewDecodedBlock(data []byte, colors *Colors) (db *DecodedBlock, err error)
version := data[0]
//var mapContent := make([]byte, uncompressedLen)
var mapContent []byte
if version >= 29 {
return decode29(data, colors)
}
var offset int
if version >= 29 {
dec, err := zstd.NewReader(nil)
if err != nil {
return nil, err
}
mapContent, err = dec.DecodeAll(data[1:], nil)
if err != nil {
return nil, err
}
} else {
contentWidth := Min(int(data[2]), 2)
paramsWidth := Min(int(data[3]), 2)
@ -143,7 +261,7 @@ func NewDecodedBlock(data []byte, colors *Colors) (db *DecodedBlock, err error)
return
}
mapContent = make([]byte, uncompressedLen)
mapContent := make([]byte, uncompressedLen)
var k int
k, err = io.ReadFull(zr, mapContent)
@ -198,7 +316,6 @@ func NewDecodedBlock(data []byte, colors *Colors) (db *DecodedBlock, err error)
offset += 2 + 10*num
}
}
}
offset++
if offset+1 >= dataLen {