Files
go-nostr/negentropy/vector.go
2024-09-11 21:23:38 -03:00

82 lines
1.6 KiB
Go

package negentropy
import (
"errors"
"sort"
)
type Vector struct {
items []Item
}
func NewVector() *Vector {
return &Vector{
items: make([]Item, 0, 30),
}
}
func (v *Vector) Insert(createdAt uint64, id string) error {
// fmt.Fprintln(os.Stderr, "Insert", createdAt, id)
if len(id) != IDSize*2 {
return errors.New("bad id size for added item")
}
item := NewItem(createdAt, id)
v.items = append(v.items, *item)
return nil
}
func (v *Vector) Seal() error {
sort.Slice(v.items, func(i, j int) bool {
return v.items[i].LessThan(v.items[j])
})
for i := 1; i < len(v.items); i++ {
if v.items[i-1].Equals(v.items[i]) {
return errors.New("duplicate item inserted")
}
}
return nil
}
func (v *Vector) Size() int {
return len(v.items)
}
func (v *Vector) GetItem(i uint64) (Item, error) {
if i >= uint64(len(v.items)) {
return Item{}, errors.New("index out of bounds")
}
return v.items[i], nil
}
func (v *Vector) Iterate(begin, end int, cb func(Item, int) bool) error {
for i := begin; i < end; i++ {
if !cb(v.items[i], i) {
break
}
}
return nil
}
func (v *Vector) FindLowerBound(begin, end int, bound Bound) (int, error) {
i := sort.Search(len(v.items[begin:end]), func(i int) bool {
return !v.items[begin+i].LessThan(bound.Item)
})
return begin + i, nil
}
func (v *Vector) Fingerprint(begin, end int) (Fingerprint, error) {
var out Accumulator
out.SetToZero()
if err := v.Iterate(begin, end, func(item Item, _ int) bool {
out.AddItem(item)
return true
}); err != nil {
return Fingerprint{}, err
}
return out.GetFingerprint(end - begin), nil
}