genarray

package
v2.15.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 3, 2024 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

Package genarray implements a generational array data structure.

A generational array is a contiguous block of memory, like a vanilla array, but the array index is extended with an incrementing "generation" that allows elements to be safely invalidated and removed, and their space in the array reused for future insertions.

Each array slot supports a 64-bit generation count. In rare cases this may eventually overflow, raising a panic with ErrRange on insertion.

Security model: note that keys are predictable and keys may be leaked through timing side-channel attacks. Do not treat these keys as secret values.

Index

Examples

Constants

This section is empty.

Variables

View Source
var ErrConflict = errors.New("key conflict")
View Source
var ErrLimit = errors.New("index exceeds limit")
View Source
var ErrNotFound = errors.New("not found")
View Source
var ErrRange = errors.New("value out of range")

Functions

This section is empty.

Types

type Key

type Key struct {
	// contains filtered or unexported fields
}

A Key uniquely references a value in a Store.

func KeyFromBytes

func KeyFromBytes(src []byte) Key

KeyFromBytes decodes a key from an opaque 16-byte value. Provided a Store uses the same mask each time, this value is stable across different processes.

If src is not at least 16 bytes long, panics with io.ErrShortBuffer.

func ReadKey

func ReadKey(r io.Reader) (Key, error)

ReadKey Read reads and decodes a key from an opaque 16-byte value. Provided a Store uses the same mask each time, this value is stable across different processes.

func (Key) Bytes

func (k Key) Bytes(dest []byte)

Bytes encodes a key as an opaque 16-byte value. Provided a Store uses the same mask each time, this value is stable across different processes.

If dest is not large enough to receive 16 bytes, panics with io.ErrShortBuffer.

func (Key) LessThan added in v2.13.0

func (k Key) LessThan(other Key) bool

LessThan implements an ordering of keys. Invalid keys (deleted keys, etc.) have an arbitrary ordering. The ordering matches that generated by [Keys].

func (Key) Write

func (k Key) Write(w io.Writer) error

Write encodes and writes a key as an opaque 16-byte value. Provided a Store uses the same mask each time, this value is stable across different processes.

type Store

type Store[ValueT any] struct {
	// contains filtered or unexported fields
}

Store is a collection of values, indexed by a unique key. The zero-value for a store is a useful value.

Example
package main

import (
	"fmt"

	"github.com/tawesoft/golib/v2/ds/genarray"
	"github.com/tawesoft/golib/v2/must"
)

func main() {
	// declare a generational array Store
	var store genarray.Store[string]

	// insert "hello" and "world" into the Store and keep a reference
	hello := store.Insert("hello")
	world := store.Insert("world")

	// we can retrieve a value using the returned key as a reference
	value, ok := store.Get(hello)
	must.Truef(ok, "failed to lookup hello key in store")
	must.Equalf(value, "hello", "hello key lookup returned unexpected value %q", value)

	// or delete a value...
	err := store.Delete(world)
	must.Equal(err, nil)

	// after being deleted, cannot retrieve again
	value, ok = store.Get(world)
	must.Not(ok)

	// nor delete again
	err = store.Delete(world)
	must.Equal(err, genarray.ErrNotFound)

	// now insert a new element, reusing the space where "world" appeared
	// previously in the Store's backing array.
	everyone := store.Insert("everyone")

	// keys are not equal despite the space being reused
	must.Not(world == everyone)

	// let's check the contents:
	valueIterator := store.Values()
	for {
		value, ok := valueIterator()
		if !ok {
			break
		}
		fmt.Println(value)
	}
	fmt.Println(store.Count())

}
Output:

hello
everyone
2

func (*Store[ValueT]) Clear

func (s *Store[ValueT]) Clear()

Clear (re)initialises a Store so that it is empty and any backing storage is released.

func (*Store[ValueT]) Contains

func (s *Store[ValueT]) Contains(key Key) bool

Contains returns true iff the key is a valid reference to a current value.

func (*Store[ValueT]) Count

func (s *Store[ValueT]) Count() int

Count returns the number of values currently in the Store.

func (*Store[ValueT]) Delete

func (s *Store[ValueT]) Delete(key Key) error

Delete removes an entry from the Store, referenced by Key, and overwrites the value in the store with the zero value for its type in order to prevent dangling references. If not found (or already deleted previously), returns ErrNotFound. Once removed, that Key will never again be a valid reference to a value, even if the underlying memory in the Store gets reused for a new value.

func (*Store[ValueT]) Get

func (s *Store[ValueT]) Get(key Key) (ValueT, bool)

Get retrieves a copy of a value from the Store, referenced by Key. The second return value is true iff found.

func (*Store[ValueT]) Grow

func (s *Store[ValueT]) Grow(n int)

Grow increases the store's capacity, if necessary, to guarantee space for another n elements. After Grow(n), at least n elements can be appended to the store without another allocation. This is an optional optimisation.

Panics with ErrLimit if the new capacity would exceed the limit set in [Store.Init].

func (*Store[ValueT]) Index added in v2.13.0

func (s *Store[ValueT]) Index(key Key) int

Index returns an index, between 0 and Store.Count minus one inclusive, indicating, in ascending order, where a key would appear in the iteration generated by [Keys].

Panics with ErrNotFound if the key is no longer valid.

func (*Store[ValueT]) Insert

func (s *Store[ValueT]) Insert(value ValueT) Key

Insert puts a copy of value in the Store, and returns a Key which uniquely identifies it for lookup later.

In the unlikely event that the 64-bit generation counter for an entry would overflow, or in the case that the limit set in [Store.Init] is exceeded, panics with ErrRange or ErrLimit.

func (*Store[ValueT]) Keys

func (s *Store[ValueT]) Keys() func() (Key, bool)

Keys returns an iterator function that generates each stored key. The order of iteration is not defined, except that Store.Keys, Store.Values and Store.Pairs produce values in the same order. It is not safe to mutate the Store during this iteration.

func (*Store[ValueT]) Pairs

func (s *Store[ValueT]) Pairs() func() (iter.Pair[Key, ValueT], bool)

Pairs returns an iterator function that generates each stored (Key, Value) pair. The order of iteration is not defined, except that Store.Keys, Store.Values and Store.Pairs produce values in the same order. It is not safe to mutate the Store during this iteration.

func (*Store[ValueT]) ReadKeys

func (s *Store[ValueT]) ReadKeys(r io.Reader, limit int) error

ReadKeys (re)initialises a store from a binary serialisation, clearing its current contents and repopulating it with keys referencing zero values.

Limit, if greater than zero, sets an upper limit on the size (in number of elements) of the backing array. A small but maliciously crated input could otherwise consume a large amount of memory by encoding sparsely distributed keys.

It is left to the caller to deserialise values and associate them with their matching key using Store.Update.

This function reads until EOF. io.ReadLimiter may be useful.

The return value, if not nil, may be ErrLimit, ErrConflict if there is a duplicate key, or may represent an io read error.

func (*Store[ValueT]) Update

func (s *Store[ValueT]) Update(key Key, value ValueT) error

Update modifies an existing value in the Store, referenced by Key. May return ErrNotFound if the key does not reference a valid current entry. Otherwise, returns nil.

func (*Store[ValueT]) Values

func (s *Store[ValueT]) Values() func() (ValueT, bool)

Values returns an iterator function that generates each stored value. The order of iteration is not defined, except that Store.Keys, Store.Values and Store.Pairs produce values in the same order. It is not safe to mutate the Store during this iteration.

func (*Store[ValueT]) WriteKeys

func (s *Store[ValueT]) WriteKeys(w io.Writer) error

WriteKeys writes a binary serialisation of a Store's keys that can later be deserialised and associated with values.

It is left to the caller to serialise the values themselves. Note that because Store.Keys and Store.Values iterate in the same order, it is not strictly necessary to store redundant keys with the serialised values.

The return value, if not nil, may represent an io write error.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL