func (f *segmentTermsEnumFrame) scanToTermNonLeaf(target []byte,
	exactOnly bool) (status SeekStatus, err error) {
	fmt.Printf(
		"    scanToTermNonLeaf: block fp=%v prefix=%v nextEnt=%v (of %v) target=%v term=%v",
		f.fp, f.prefix, f.nextEnt, f.entCount, brToString(target), ""  )
	assert(f.nextEnt != -1)
	if f.nextEnt == f.entCount {
		panic("not implemented yet")
	}
	assert(f.prefixMatches(target))
	for {
		f.nextEnt++
		code, _ := f.suffixesReader.ReadVInt()  
		f.suffix = int(uint32(code) >> 1)
		f.ste.termExists = (code & 1) == 0
		termLen := f.prefix + f.suffix
		f.startBytePos = f.suffixesReader.Position()
		f.suffixesReader.SkipBytes(int64(f.suffix))
		if f.ste.termExists {
			f.state.TermBlockOrd++
			f.subCode = 0
		} else {
			f.subCode, _ = f.suffixesReader.ReadVLong()  
			f.lastSubFP = f.fp - f.subCode
		}
		targetLimit := termLen
		if len(target) < termLen {
			targetLimit = len(target)
		}
		targetPos := f.prefix
		bytePos := f.startBytePos
		var toNextTerm, stopScan bool
		for {
			var cmp int
			var stop bool
			if targetPos < targetLimit {
				cmp = int(f.suffixBytes[bytePos]) - int(target[targetPos])
				bytePos++
				targetPos++
				stop = false
			} else {
				assert(targetPos == targetLimit)
				cmp = termLen - len(target)
				stop = true
			}
			if cmp < 0 {
				if f.nextEnt == f.entCount {
					if exactOnly {
						f.fillTerm()
					}
					stopScan = true
					break
				} else {
					toNextTerm = true
					break
				}
			} else if cmp > 0 {
				f.fillTerm()
				if !exactOnly && !f.ste.termExists {
					panic("niy")
				}
				fmt.Println("        not found")
				return SEEK_STATUS_NOT_FOUND, nil
			} else if stop {
				assert(f.ste.termExists)
				f.fillTerm()
				fmt.Println("        found!")
				return SEEK_STATUS_FOUND, nil
			}
		}
		if toNextTerm {
			continue
		}
		if stopScan {
			break
		}
	}
	fmt.Println("      block end")
	if exactOnly {
		f.fillTerm()
	}
	return SEEK_STATUS_END, nil
}
Target's prefix matches this block's prefix; we
scan the entries check if the suffix matches.
package blocktree
import (
	"bytes"
	"fmt"
	. "github.com/balzaczyy/golucene/core/codec/spi"
	. "github.com/balzaczyy/golucene/core/index/model"
	"github.com/balzaczyy/golucene/core/store"
	"github.com/balzaczyy/golucene/core/util"
	"github.com/balzaczyy/golucene/core/util/fst"
)
type segmentTermsEnumFrame struct {
	ord int
	hasTerms     bool
	hasTermsOrig bool
	isFloor      bool
	arc *fst.Arc
	fp     int64
	fpOrig int64
	fpEnd  int64
	suffixBytes    []byte
	suffixesReader store.ByteArrayDataInput
	statBytes   []byte
	statsReader store.ByteArrayDataInput
	floorData       []byte
	floorDataReader store.ByteArrayDataInput
	prefix int
	entCount int
	nextEnt int
	isLastInFloor bool
	isLeafBlock bool
	lastSubFP int64
	nextFloorLabel       int
	numFollowFloorBlocks int
	metaDataUpto int
	state *BlockTermState
	longs []int64
	bytes       []byte
	bytesReader *store.ByteArrayDataInput
	ste *SegmentTermsEnum
	startBytePos int
	suffix       int
	subCode      int64
}
func newFrame(ste *SegmentTermsEnum, ord int) *segmentTermsEnumFrame {
	f := &segmentTermsEnumFrame{
		suffixBytes: make([]byte, 128),
		statBytes:   make([]byte, 64),
		floorData:   make([]byte, 32),
		ste:         ste,
		ord:         ord,
		longs:       make([]int64, ste.fr.longsSize),
	}
	f.state = ste.fr.parent.postingsReader.NewTermState()
	f.state.TotalTermFreq = -1
	return f
}
func (f *segmentTermsEnumFrame) setFloorData(in *store.ByteArrayDataInput, source []byte) {
	numBytes := len(source) - (in.Pos - 0)
	if numBytes > len(f.floorData) {
		f.floorData = make([]byte, numBytes)
	}
	copy(f.floorData, source[in.Pos:])
	f.floorDataReader.Reset(f.floorData)
	f.numFollowFloorBlocks, _ = asInt(f.floorDataReader.ReadVInt())
	b, _ := f.floorDataReader.ReadByte()
	f.nextFloorLabel = int(b)
}
func (f *segmentTermsEnumFrame) getTermBlockOrd() int {
	if f.isLeafBlock {
		return f.nextEnt
	} else {
		return f.state.TermBlockOrd
	}
}
func (f *segmentTermsEnumFrame) loadBlock() (err error) {
	f.ste.initIndexInput()
	if f.nextEnt != -1 {
		return
	}
	f.ste.in.Seek(f.fp)
	code, err := asInt(f.ste.in.ReadVInt())
	if err != nil {
		return err
	}
	f.entCount = int(uint(code) >> 1)
	assert(f.entCount > 0)
	f.isLastInFloor = (code & 1) != 0
	assert2(f.arc == nil || !f.isLastInFloor || !f.isFloor,
		"fp=%v arc=%v isFloor=%v isLastInFloor=%v",
		f.fp, f.arc, f.isFloor, f.isLastInFloor)
	code, err = asInt(f.ste.in.ReadVInt())
	if err != nil {
		return err
	}
	f.isLeafBlock = (code & 1) != 0
	numBytes := int(uint(code) >> 1)
	if len(f.suffixBytes) < numBytes {
		f.suffixBytes = make([]byte, numBytes)
	}
	err = f.ste.in.ReadBytes(f.suffixBytes[:numBytes])
	if err != nil {
		return err
	}
	f.suffixesReader.Reset(f.suffixBytes)
	numBytes, err = asInt(f.ste.in.ReadVInt())
	if err != nil {
		return err
	}
	if len(f.statBytes) < numBytes {
		f.statBytes = make([]byte, numBytes)
	}
	err = f.ste.in.ReadBytes(f.statBytes[:numBytes])
	if err != nil {
		return err
	}
	f.statsReader.Reset(f.statBytes)
	f.metaDataUpto = 0
	f.state.TermBlockOrd = 0
	f.nextEnt = 0
	f.lastSubFP = -1
	if numBytes, err = asInt(f.ste.in.ReadVInt()); err != nil {
		return err
	}
	if f.bytes == nil {
		f.bytes = make([]byte, util.Oversize(numBytes, 1))
		f.bytesReader = store.NewEmptyByteArrayDataInput()
	} else if len(f.bytes) < numBytes {
		f.bytes = make([]byte, util.Oversize(numBytes, 1))
	}
	if err = f.ste.in.ReadBytes(f.bytes[:numBytes]); err != nil {
		return err
	}
	f.bytesReader.Reset(f.bytes)
	f.fpEnd = f.ste.in.FilePointer()
	return nil
}
func (f *segmentTermsEnumFrame) rewind() {
	f.fp = f.fpOrig
	f.nextEnt = -1
	f.hasTerms = f.hasTermsOrig
	if f.isFloor {
		f.floorDataReader.Rewind()
		f.numFollowFloorBlocks, _ = asInt(f.floorDataReader.ReadVInt())
		assert(f.numFollowFloorBlocks > 0)
		b, _ := f.floorDataReader.ReadByte()
		f.nextFloorLabel = int(b)
	}
}
func (f *segmentTermsEnumFrame) next() bool {
	if f.isLeafBlock {
		return f.nextLeaf()
	}
	return f.nextNonLeaf()
}
func (f *segmentTermsEnumFrame) nextLeaf() bool {
	panic("not implemented yet")
}
func (f *segmentTermsEnumFrame) nextNonLeaf() bool {
	panic("not implemented yet")
}
func (f *segmentTermsEnumFrame) scanToFloorFrame(target []byte) {
	if !f.isFloor || len(target) <= f.prefix {
		return
	}
	targetLabel := int(target[f.prefix])
	fmt.Printf("    scanToFloorFrame fpOrig=%v targetLabel=%x vs nextFloorLabel=%x numFollowFloorBlocks=%v\n",
		f.fpOrig, targetLabel, f.nextFloorLabel, f.numFollowFloorBlocks)
	if targetLabel < f.nextFloorLabel {
		fmt.Println("      already on correct block")
		return
	}
	assert(f.numFollowFloorBlocks != 0)
	var newFP int64
	for {
		code, _ := f.floorDataReader.ReadVLong()  
		newFP = f.fpOrig + int64(uint64(code)>>1)
		f.hasTerms = (code & 1) != 0
		f.isLastInFloor = f.numFollowFloorBlocks == 1
		f.numFollowFloorBlocks--
		if f.isLastInFloor {
			f.nextFloorLabel = 256
			fmt.Printf("        stop!  last block nextFloorLabel=%x\n", f.nextFloorLabel)
			break
		} else {
			panic("niy")
		}
	}
	if newFP != f.fp {
		fmt.Printf("      force switch to fp=%v oldFP=%v\n", newFP, f.fp)
		f.nextEnt = -1
		f.fp = newFP
	} else {
	}
}
func (f *segmentTermsEnumFrame) decodeMetaData() (err error) {
	limit := f.getTermBlockOrd()
	absolute := f.metaDataUpto == 0
	assert(limit > 0)
	for f.metaDataUpto < limit {
		if f.state.DocFreq, err = asInt(f.statsReader.ReadVInt()); err != nil {
			return err
		}
		if f.ste.fr.fieldInfo.IndexOptions() != INDEX_OPT_DOCS_ONLY {
			var n int64
			if n, err = f.statsReader.ReadVLong(); err != nil {
				return err
			}
			f.state.TotalTermFreq = int64(f.state.DocFreq) + n
		}
		for i := 0; i < f.ste.fr.longsSize; i++ {
			if f.longs[i], err = f.bytesReader.ReadVLong(); err != nil {
				return err
			}
		}
		if err = f.ste.fr.parent.postingsReader.DecodeTerm(f.longs,
			f.bytesReader, f.ste.fr.fieldInfo, f.state, absolute); err != nil {
			return err
		}
		f.metaDataUpto++
		absolute = false
	}
	f.state.TermBlockOrd = f.metaDataUpto
	return nil
}
func (f *segmentTermsEnumFrame) prefixMatches(target []byte) bool {
	for i := 0; i < f.prefix; i++ {
		if target[i] != f.ste.term.At(i) {
			return false
		}
	}
	return true
}
func (f *segmentTermsEnumFrame) scanToTerm(target []byte, exactOnly bool) (status SeekStatus, err error) {
	if f.isLeafBlock {
		return f.scanToTermLeaf(target, exactOnly)
	}
	return f.scanToTermNonLeaf(target, exactOnly)
}
func (f *segmentTermsEnumFrame) scanToTermLeaf(target []byte, exactOnly bool) (status SeekStatus, err error) {
	assert(f.nextEnt != -1)
	f.ste.termExists = true
	f.subCode = 0
	if f.nextEnt == f.entCount {
		if exactOnly {
			f.fillTerm()
		}
		return SEEK_STATUS_END, nil
	}
	if !f.prefixMatches(target) {
		panic("assert fail")
	}
	for {
		f.nextEnt++
		f.suffix, err = asInt(f.suffixesReader.ReadVInt())
		if err != nil {
			return 0, err
		}
		termLen := f.prefix + f.suffix
		f.startBytePos = f.suffixesReader.Pos
		f.suffixesReader.SkipBytes(int64(f.suffix))
		targetLimit := termLen
		if len(target) < termLen {
			targetLimit = len(target)
		}
		targetPos := f.prefix
		bytePos := f.startBytePos
		isDone := false
		for {
			var cmp int
			var stop bool
			if targetPos < targetLimit {
				cmp = int(f.suffixBytes[bytePos]) - int(target[targetPos])
				bytePos++
				targetPos++
				stop = false
			} else {
				if targetPos != targetLimit {
					panic("assert fail")
				}
				cmp = termLen - len(target)
				stop = true
			}
			if cmp < 0 {
				if f.nextEnt == f.entCount {
					if exactOnly {
						f.fillTerm()
					}
					isDone = true
				}
				break
			} else if cmp > 0 {
				f.fillTerm()
				return SEEK_STATUS_NOT_FOUND, nil
			} else if stop {
				assert(f.ste.termExists)
				f.fillTerm()
				return SEEK_STATUS_FOUND, nil
			}
		}
		if isDone {
			break
		}
	}
	fmt.Println("      block end")
	if exactOnly {
		f.fillTerm()
	}
	return SEEK_STATUS_END, nil
}