Factor out big endian reader

This commit is contained in:
Sascha L. Teichmann 2024-01-07 15:31:42 +01:00
parent e36b61adbe
commit 8f0935a245
2 changed files with 99 additions and 87 deletions

80
common/bigendianreader.go Normal file
View File

@ -0,0 +1,80 @@
// Copyright 2024 by Sascha L. Teichmann
// Use of this source code is governed by the MIT license
// that can be found in the LICENSE file.
package common
import (
"encoding/binary"
"io"
)
type bigEndianReader struct {
parent io.Reader
buf [4]byte
err error
}
func (ber *bigEndianReader) u8() (uint8, error) {
if ber.err != nil {
return 0, ber.err
}
_, err := io.ReadFull(ber.parent, ber.buf[:1])
if err != nil {
ber.err = err
return 0, err
}
return ber.buf[0], nil
}
func (ber *bigEndianReader) u16() (uint16, error) {
if ber.err != nil {
return 0, ber.err
}
two := ber.buf[:2]
_, err := io.ReadFull(ber.parent, two)
if err != nil {
ber.err = err
return 0, err
}
return binary.BigEndian.Uint16(two), nil
}
func (ber *bigEndianReader) u32() (uint32, error) {
if ber.err != nil {
return 0, ber.err
}
four := ber.buf[:2]
_, err := io.ReadFull(ber.parent, four)
if err != nil {
ber.err = err
return 0, err
}
return binary.BigEndian.Uint32(four), nil
}
func (ber *bigEndianReader) str(n int) (string, error) {
if ber.err != nil {
return "", ber.err
}
buf := make([]byte, n)
_, err := io.ReadFull(ber.parent, buf)
if err != nil {
ber.err = err
return "", err
}
return string(buf), nil
}
func (ber *bigEndianReader) full(n int) ([]byte, error) {
if ber.err != nil {
return nil, ber.err
}
buf := make([]byte, n)
_, err := io.ReadFull(ber.parent, buf)
if err != nil {
ber.err = err
return nil, err
}
return buf, nil
}

View File

@ -92,101 +92,38 @@ 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)
dec, err := zstd.NewReader(bytes.NewReader(data))
if err != nil {
return nil, err
}
content, err := dec.DecodeAll(data[1:], nil)
if err != nil {
return nil, err
}
be := bigEndianReader{parent: dec}
be := bigEndian{data: content}
_ = be.u8() // flags
_ = be.u16() // lightning_complete
_ = be.u32() // timestamp
_ = be.u8() // name_id_mapping_version
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()
numNameIDMappings, _ := be.u16()
for i := uint16(0); i < numNameIDMappings; i++ {
id := int32(be.u16())
name := be.str(int(be.u16()))
var (
id, _ = be.u16()
nlen, _ = be.u16()
name, _ = be.str(int(nlen))
)
switch name {
case "air":
airID = id
airID = int32(id)
case "ignore":
ignoreID = id
ignoreID = int32(id)
default:
if index, found := colors.NameIndex[name]; found {
indexMap[id] = index
indexMap[int32(id)] = index
if !transparent && colors.IsTransparent(index) {
transparent = true
}
@ -195,18 +132,13 @@ func decode29(data []byte, colors *Colors) (*DecodedBlock, error) {
}
}
}
_ = be.u8() // content_width
_ = be.u8() // params_width
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) {
mapContent, err := be.full(2 * 4096)
if err != nil {
return nil, ErrBlockTruncated
}
copy(mapContent, be.data)
return &DecodedBlock{
Version: data[0],