func (fr *Reader) readBlock(fileOff int64) error {
	fb := &fr.fb
	fr.rio.Seek(recordio.ItemLocation{uint64(fileOff), 0})
	if !fr.rio.Scan() {
		err := fr.rio.Err()
		if err == nil {
			err = fmt.Errorf("%s: read block (offset %d)", fr.label, fileOff)
		}
		return err
	}
	fb.buf = fr.rio.Get().([]byte)
	var err error
	fb.header, err = readBlockHeader(&fb.buf)
	return err
}
Read a block from recordio and uncompress it.
package fieldio
import (
	"context"
	"encoding/binary"
	"fmt"
	"reflect"
	"sync/atomic"
	"unsafe"
	"github.com/grailbio/base/errors"
	"github.com/grailbio/base/file"
	"github.com/grailbio/base/log"
	"github.com/grailbio/base/morebufio"
	"github.com/grailbio/base/recordio"
	"github.com/grailbio/base/traverse"
	gunsafe "github.com/grailbio/base/unsafe"
	"github.com/grailbio/bio/biopb"
	gbam "github.com/grailbio/bio/encoding/bam"
	"github.com/grailbio/bio/encoding/pam/pamutil"
	"github.com/grailbio/hts/sam"
)
type Reader struct {
	label  string                      
	in     file.File                   
	rio    recordio.Scanner            
	index  biopb.PAMFieldIndex         
	blocks []biopb.PAMBlockIndexEntry  
	fb     fieldReadBuf                
	err    *errors.Once
	coordField    bool                 
	addrGenerator gbam.CoordGenerator  
}
type readerOpts struct {
	bufSize int
}
type ReaderOpt func(*readerOpts)
func BufSize(size int) ReaderOpt {
	return func(opts *readerOpts) {
		opts.bufSize = size
	}
}
func NewReader(ctx context.Context, path, label string, coordField bool, fileOpts file.Opts, errp *errors.Once, opts ...ReaderOpt) (*Reader, error) {
	var ropts readerOpts
	for _, opt := range opts {
		opt(&ropts)
	}
	fr := &Reader{
		coordField: coordField,
		label:      label,
		err:        errp,
	}
	in, err := file.Open(ctx, path, fileOpts)
	if err != nil {
		if e, ok := err.(*errors.Error); ok && e.Kind == errors.NotExist {
			return nil, nil
		}
		return fr, errors.E(err, fmt.Sprintf("fieldio open %s: %s", path, label))
	}
	fr.in = in
	frReader := fr.in.Reader(ctx)
	if ropts.bufSize > 0 {
		frReader = morebufio.NewReadSeekerSize(frReader, ropts.bufSize)
	}
	fr.rio = recordio.NewScanner(frReader, recordio.ScannerOpts{})
	fr.addrGenerator = gbam.NewCoordGenerator()
	trailer := fr.rio.Trailer()
	if len(trailer) == 0 {
		return fr, errors.E(fr.rio.Err(), fmt.Sprintf("fieldio open %v: file does not contain an index", path))
	}
	if err := fr.index.Unmarshal(trailer); err != nil {
		return fr, errors.E(err, fmt.Sprintf("fieldio open %s: Failed to unmarshal field index for %s", path, label))
	}
	return fr, nil
}
type fieldReadBuf struct {
	header              biopb.PAMBlockHeader
	index               biopb.PAMBlockIndexEntry
	buf                 []byte  
	defaultBuf, blobBuf byteBuffer
	remaining           int    
	prevInt64Value0     int64  
	prevInt64Value1     int64
	prevString          []byte  
	tmpAuxMd            AuxMetadata
}
func (rb *fieldReadBuf) reset(index biopb.PAMBlockIndexEntry, buf []byte, blob []byte) {
	rb.index = index
	rb.remaining = int(index.NumRecords)
	rb.defaultBuf = buf
	rb.blobBuf = blob
	rb.prevInt64Value0 = 0
	rb.prevInt64Value1 = 0
	rb.prevString = rb.prevString[:0]
}
type StringDeltaMetadata struct {
	PrefixLen int  
	DeltaLen  int  
}
func (fr *Reader) ReadStringDeltaMetadata() (StringDeltaMetadata, bool) {
	if fr.fb.remaining <= 0 && !fr.readNextBlock() {
		return StringDeltaMetadata{}, false
	}
	rb := &fr.fb
	return StringDeltaMetadata{
		PrefixLen: int(rb.defaultBuf.Uvarint32()),
		DeltaLen:  int(rb.defaultBuf.Uvarint32()),
	}, true
}
func (fr *Reader) SkipStringDeltaField() {
	rb := &fr.fb
	rb.remaining--
	md, ok := fr.ReadStringDeltaMetadata()
	if !ok {
		panic(fr)
	}
	prefix := rb.prevString[:md.PrefixLen]
	resizeBuf(&rb.prevString, md.PrefixLen+md.DeltaLen)
	copy(rb.prevString, prefix)
	copy(rb.prevString[md.PrefixLen:], rb.blobBuf.RawBytes(md.DeltaLen))
}
func (fr *Reader) ReadStringDeltaField(md StringDeltaMetadata, arena *UnsafeArena) string {
	rb := &fr.fb
	rb.remaining--
	if md.PrefixLen < 0 {
		log.Panic(md)
	}
	destBuf := arena.Alloc(md.PrefixLen + md.DeltaLen)
	if md.PrefixLen > 0 {
		copy(destBuf, rb.prevString[:md.PrefixLen])
	}
	copy(destBuf[md.PrefixLen:], rb.blobBuf.RawBytes(md.DeltaLen))
	resizeBuf(&rb.prevString, len(destBuf))
	copy(rb.prevString, destBuf)
	return gunsafe.BytesToString(destBuf)
}
func (fr *Reader) ReadVarintDeltaField() (int64, bool) {
	if fr.fb.remaining <= 0 && !fr.readNextBlock() {
		return 0, false
	}
	rb := &fr.fb
	rb.remaining--
	delta := rb.defaultBuf.Varint64()
	value := rb.prevInt64Value0 + delta
	rb.prevInt64Value0 = value
	return value, true
}
func (fr *Reader) ReadVarintField() (int64, bool) {
	if fr.fb.remaining <= 0 && !fr.readNextBlock() {
		return 0, false
	}
	rb := &fr.fb
	rb.remaining--
	return rb.defaultBuf.Varint64(), true
}
func (fr *Reader) SkipVarintField() {
	if _, ok := fr.ReadVarintField(); !ok {
		panic(fr)
	}
}
func (fr *Reader) ReadUint8Field() (uint8, bool) {
	if fr.fb.remaining <= 0 && !fr.readNextBlock() {
		return 0, false
	}
	rb := &fr.fb
	rb.remaining--
	return rb.defaultBuf.Uint8(), true
}
func (fr *Reader) SkipUint8Field() {
	if _, ok := fr.ReadUint8Field(); !ok {
		panic(fr)
	}
}
func (fr *Reader) ReadUint16Field() (uint16, bool) {
	if fr.fb.remaining <= 0 && !fr.readNextBlock() {
		return 0, false
	}
	rb := &fr.fb
	rb.remaining--
	return rb.defaultBuf.Uint16(), true
}
func (fr *Reader) SkipUint16Field() {
	if _, ok := fr.ReadUint16Field(); !ok {
		panic(fr)
	}
}
func (fr *Reader) ReadFloat64Field() (float64, bool) {
	if fr.fb.remaining <= 0 && !fr.readNextBlock() {
		return 0.0, false
	}
	rb := &fr.fb
	rb.remaining--
	return rb.defaultBuf.Float64(), true
}
func (fr *Reader) SkipFloat64Field() {
	if _, ok := fr.ReadFloat64Field(); !ok {
		panic(fr)
	}
}