func EncodeBlock(data []byte) ([]byte, error) {
	if len(data) > MaximumBlockSize {
		return nil, errors.New("data exceeds maximum block size")
	}
	var buffer bytes.Buffer
	gzw := gzip.NewWriter(&buffer)
	gzw.Header.Extra = []byte{
		0x42, 0x43,  
		0x02, 0x00,  
		0x88, 0x88,  
	}
	if _, err := gzw.Write(data); err != nil {
		return nil, fmt.Errorf("writing compressed data: %v", err)
	}
	if err := gzw.Close(); err != nil {
		return nil, fmt.Errorf("closing writer: %v", err)
	}
	bsize := buffer.Len() - 1
	encoded := buffer.Bytes()
	encoded[16] = byte(bsize)
	encoded[17] = byte(bsize >> 8)
	return encoded, nil
}
EncodeBlock returns a single BGZF block that encodes the bytes in data.
package bgzf
import (
	"bytes"
	"compress/gzip"
	"errors"
	"fmt"
	"io"
	"sort"
	"strconv"
)
const LastAddress = Address(0xffffffffffffffff)
const MaximumBlockSize = 65536
type Address uint64
func (v Address) BlockOffset() uint64 {
	return uint64(v >> 16)
}
func (v Address) DataOffset() uint16 {
	return uint16(v & 0xffff)
}
func (v Address) String() string {
	return strconv.FormatUint(uint64(v), 16)
}
func ParseAddress(input string) (Address, error) {
	v, err := strconv.ParseUint(input, 16, 64)
	return Address(v), err
}
func NewAddress(blockOffset uint64, dataOffset uint16) Address {
	return Address(blockOffset<<16 | uint64(dataOffset))
}
type Chunk struct {
	Start, End Address
}
func (v *Chunk) String() string {
	return fmt.Sprintf("[%s-%s]", v.Start, v.End)
}
func Merge(input []*Chunk, sizeLimit uint64) []*Chunk {
	sort.Slice(input, func(i, j int) bool {
		return input[i].Start < input[j].Start
	})
	var (
		merged = []*Chunk{input[0]}
		output = merged[0]
	)
	for i := 1; i < len(input); i++ {
		var size uint64
		if input[i].End.BlockOffset() == output.Start.BlockOffset() {
			size = uint64(input[i].End.DataOffset() - output.Start.DataOffset())
		} else {
			size = input[i].End.BlockOffset() - output.Start.BlockOffset() + MaximumBlockSize
		}
		if input[i].Start <= output.End && size <= sizeLimit {
			if output.End < input[i].End {
				output.End = input[i].End
			}
		} else {
			merged = append(merged, input[i])
			output = merged[len(merged)-1]
		}
	}
	return merged
}
func DecodeBlock(r io.Reader) ([]byte, uint16, error) {
	gzr, err := gzip.NewReader(r)
	if err != nil {
		return nil, 0, fmt.Errorf("initializing gzip reader: %v", err)
	}
	defer gzr.Close()
	extra := gzr.Header.Extra
	if extra[0] != 0x42 || extra[1] != 0x43 {
		return nil, 0, fmt.Errorf("unexpected extra ID: %x", extra[0:2])
	}
	if extra[2] != 2 || extra[3] != 0 {
		return nil, 0, fmt.Errorf("unexpected extra length: %x", extra[2:4])
	}
	gzr.Multistream(false)
	var buffer bytes.Buffer
	if _, err := io.Copy(&buffer, gzr); err != nil {
		return nil, 0, fmt.Errorf("decompressing data: %v", err)
	}
	return buffer.Bytes(), (uint16(extra[4]) | uint16(extra[5])<<8) + 1, nil
}