109 lines
1.7 KiB
Go
109 lines
1.7 KiB
Go
|
package index
|
||
|
|
||
|
import (
|
||
|
"encoding/binary"
|
||
|
"errors"
|
||
|
"io"
|
||
|
)
|
||
|
|
||
|
const pageSize = 2048
|
||
|
|
||
|
var errPageFull = errors.New("page full")
|
||
|
|
||
|
type pageCursor interface {
|
||
|
Iterator
|
||
|
append(v DocID) error
|
||
|
}
|
||
|
|
||
|
type page interface {
|
||
|
cursor() pageCursor
|
||
|
init(v DocID) error
|
||
|
data() []byte
|
||
|
}
|
||
|
|
||
|
type pageDelta struct {
|
||
|
b []byte
|
||
|
}
|
||
|
|
||
|
type pageType uint8
|
||
|
|
||
|
const (
|
||
|
pageTypeDelta pageType = iota
|
||
|
)
|
||
|
|
||
|
func newPageDelta(data []byte) *pageDelta {
|
||
|
return &pageDelta{b: data}
|
||
|
}
|
||
|
|
||
|
func (p *pageDelta) init(v DocID) error {
|
||
|
// Write first value.
|
||
|
binary.PutUvarint(p.b, uint64(v))
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (p *pageDelta) cursor() pageCursor {
|
||
|
return &pageDeltaCursor{data: p.b}
|
||
|
}
|
||
|
|
||
|
func (p *pageDelta) data() []byte {
|
||
|
return p.b
|
||
|
}
|
||
|
|
||
|
type pageDeltaCursor struct {
|
||
|
data []byte
|
||
|
pos int
|
||
|
cur DocID
|
||
|
}
|
||
|
|
||
|
func (p *pageDeltaCursor) append(id DocID) error {
|
||
|
// Run to the end.
|
||
|
_, err := p.Next()
|
||
|
for ; err == nil; _, err = p.Next() {
|
||
|
// Consume.
|
||
|
}
|
||
|
if err != io.EOF {
|
||
|
return err
|
||
|
}
|
||
|
if len(p.data)-p.pos < binary.MaxVarintLen64 {
|
||
|
return errPageFull
|
||
|
}
|
||
|
if p.cur >= id {
|
||
|
return errOutOfOrder
|
||
|
}
|
||
|
p.pos += binary.PutUvarint(p.data[p.pos:], uint64(id-p.cur))
|
||
|
p.cur = id
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (p *pageDeltaCursor) Close() error {
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (p *pageDeltaCursor) Seek(min DocID) (v DocID, err error) {
|
||
|
if min < p.cur {
|
||
|
p.pos = 0
|
||
|
}
|
||
|
for v, err = p.Next(); err == nil && v < min; v, err = p.Next() {
|
||
|
// Consume.
|
||
|
}
|
||
|
return p.cur, err
|
||
|
}
|
||
|
|
||
|
func (p *pageDeltaCursor) Next() (DocID, error) {
|
||
|
var n int
|
||
|
var dv uint64
|
||
|
if p.pos == 0 {
|
||
|
dv, n = binary.Uvarint(p.data)
|
||
|
p.cur = DocID(dv)
|
||
|
} else {
|
||
|
dv, n = binary.Uvarint(p.data[p.pos:])
|
||
|
if n <= 0 || dv == 0 {
|
||
|
return 0, io.EOF
|
||
|
}
|
||
|
p.cur += DocID(dv)
|
||
|
}
|
||
|
p.pos += n
|
||
|
|
||
|
return p.cur, nil
|
||
|
}
|