func ReadIndex(rawr io.Reader) (*Index, error) {
	r := bufio.NewReaderSize(rawr, 4<<20)
	i := &Index{}
	if _, err := io.ReadFull(r, i.Magic[0:]); err != nil {
		return nil, err
	}
	if i.Magic != [4]byte{'B', 'A', 'I', 0x1} {
		return nil, fmt.Errorf("bam index invalid magic: %v", i.Magic)
	}
	var refCount int32
	if err := binary.Read(r, binary.LittleEndian, &refCount); err != nil {
		return nil, err
	}
	i.Refs = make([]Reference, refCount)
	for refId := 0; int32(refId) < refCount; refId++ {
		var binCount int32
		if err := binary.Read(r, binary.LittleEndian, &binCount); err != nil {
			return nil, err
		}
		ref := Reference{
			Bins: make([]Bin, 0, binCount),
		}
		for b := 0; int32(b) < binCount; b++ {
			var binNum uint32
			if err := binary.Read(r, binary.LittleEndian, &binNum); err != nil {
				return nil, err
			}
			var chunkCount int32
			if err := binary.Read(r, binary.LittleEndian, &chunkCount); err != nil {
				return nil, err
			}
			bin := Bin{
				BinNum: binNum,
				Chunks: make([]Chunk, chunkCount),
			}
			for c := 0; int32(c) < chunkCount; c++ {
				var beginOffset uint64
				if err := binary.Read(r, binary.LittleEndian, &beginOffset); err != nil {
					return nil, err
				}
				var endOffset uint64
				if err := binary.Read(r, binary.LittleEndian, &endOffset); err != nil {
					return nil, err
				}
				bin.Chunks[c] = Chunk{
					Begin: toOffset(beginOffset),
					End:   toOffset(endOffset),
				}
			}
			if binNum == 37450 {
				if len(bin.Chunks) != 2 {
					return nil, fmt.Errorf("invalid metadata: chunk has %d chunks, should have 2", len(bin.Chunks))
				}
				ref.Meta = Metadata{
					UnmappedBegin: fromOffset(bin.Chunks[0].Begin),
					UnmappedEnd:   fromOffset(bin.Chunks[0].End),
					MappedCount:   fromOffset(bin.Chunks[1].Begin),
					UnmappedCount: fromOffset(bin.Chunks[1].End),
				}
			} else {
				ref.Bins = append(ref.Bins, bin)
			}
		}
		var intervalCount int32
		if err := binary.Read(r, binary.LittleEndian, &intervalCount); err != nil {
			return nil, err
		}
		ref.Intervals = make([]bgzf.Offset, intervalCount)
		for inv := 0; int32(inv) < intervalCount; inv++ {
			var ioffset uint64
			if err := binary.Read(r, binary.LittleEndian, &ioffset); err != nil {
				return nil, err
			}
			ref.Intervals[inv] = toOffset(ioffset)
		}
		i.Refs[refId] = ref
	}
	var unmappedCount uint64
	if err := binary.Read(r, binary.LittleEndian, &unmappedCount); err == nil {
		i.UnmappedCount = &unmappedCount
	} else if err != nil && err != io.EOF {
		return nil, err
	}
	return i, nil
}
ReadIndex parses the content of r and returns an Index or nil and an error.
package bam
import (
	"bufio"
	"encoding/binary"
	"fmt"
	"io"
	"sort"
	"github.com/grailbio/hts/bgzf"
)
type Index struct {
	Magic         [4]byte
	Refs          []Reference
	UnmappedCount *uint64
}
type Reference struct {
	Bins      []Bin
	Intervals []bgzf.Offset
	Meta      Metadata
}
type Bin struct {
	BinNum uint32
	Chunks []Chunk
}
type Chunk struct {
	Begin bgzf.Offset
	End   bgzf.Offset
}
type Metadata struct {
	UnmappedBegin uint64
	UnmappedEnd   uint64
	MappedCount   uint64
	UnmappedCount uint64
}