diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3d8971c --- /dev/null +++ b/.gitignore @@ -0,0 +1,12 @@ +/vendor +_* +go.sum +go.sum +go.work +vendor/ +_* +benchmark* +.claude* +claude* +CLAUDE* +coverage* diff --git a/CHANGELOG.md b/CHANGELOG.md index 673382f..e33598c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,26 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - **Minor**: feature additions, removal of deprecated features - **Patch**: bug fixes, backward compatible protobuf model changes, etc. +# v2.2.0 - 2026-05-23 +#### Added +* `model.Model.GetData()` — returns snapshots of the data set and key/index maps; implementations must not expose internal storage directly +* `model.Model.Reverse()` — reverses the order of the data store +* `sorter.SortByValue` — zero-value `SortFlag`; type-stratified sort (nil < bool < numeric < string < other); now the default sort behavior +* `sorter.SortAsc`, `SortDesc`, `SortAsString`, `SortReverse` — explicit bitflag sort options +* `.gitignore` + +#### Changed +* `model.ModelTypeHash` / `model.ModelTypeList` renamed to `model.HASH` / `model.LIST`; order swapped so `HASH` is the zero/iota value +* `model.Model.Filter` callback signature changed from `func(Value) Model` to `func(Value) bool` +* `model.Model.Map` callback signature changed from `func(Value) Model` to `func(Value) Value` +* `model.Model.Reduce` callback signature changed from `func(Value) bool` to `func(carry, cur Value) Value` (standard fold semantics) +* `model.Model.SetID` now returns `error` +* `sorter.SortFlag` underlying type changed from `int` to `uint` +* `sorter.Sorter.Reverse` signature changed from `Reverse(SortFlag) error` to `Reverse() error` + +#### Fixed +* `errors/error.go` package declaration corrected from `package error` to `package errors` + # v2.1.0 - 2020-05-30 #### Added * `Caller` package diff --git a/errors/error.go b/errors/error.go index bb44660..2b07943 100644 --- a/errors/error.go +++ b/errors/error.go @@ -1,4 +1,4 @@ -package error +package errors import ( "github.com/bdlm/std/v2/caller" diff --git a/model/model.go b/model/model.go index 8438c46..1827285 100644 --- a/model/model.go +++ b/model/model.go @@ -4,12 +4,13 @@ package model type ModelType int const ( - // ModelTypeList causes the model to behave as a list (keys are unsigned, - // contiguous integers beginning at 0). - ModelTypeList ModelType = iota - // ModelTypeHash causes the model to behave as a hash (keys are strings, + // HASH causes the model to behave as a hash (keys are strings, // order is static). - ModelTypeHash + HASH ModelType = iota + + // LIST causes the model to behave as a list (keys are unsigned, + // contiguous integers beginning at 0). + LIST ) // Model is a list or a map of Values. @@ -23,10 +24,23 @@ type Model interface { Delete(key interface{}) error // Filter filters elements of the data using a callback function and // returns the result. - Filter(callback func(Value) Model) Model + Filter(callback func(Value) bool) Model // Get returns the specified data value in this model. Get(key interface{}) (Value, error) - // GetID returns returns this model's id. + // GetData returns snapshots of the current data set and indexes. + // + // Implementations must not expose internal slice or map storage directly; + // the returned slice and maps must be safe for the caller to read and + // modify without affecting the model's internal state. + // + // The return values are: + // - data: a snapshot of the model's values in model order. + // - keyToIndex: a snapshot of hash keys to indexes for HASH models; nil + // for LIST models. + // - indexToKey: a snapshot of indexes to hash keys for HASH models; nil + // for LIST models. + GetData() ([]interface{}, map[string]int, map[int]string) + // GetID returns this model's id. GetID() interface{} // GetType returns the model type. GetType() ModelType @@ -36,22 +50,39 @@ type Model interface { Lock() // Map applies a callback to all elements in this model and returns the // result. - Map(callback func(Value) Model) Model + Map(callback func(Value) Value) Model // Merge merges data from any Model into this Model. Merge(Model) error // Push a value to the end of the internal data store. Push(value interface{}) error - // Reduce iteratively reduces the data set to a single value using a - // callback function and returns the result. - Reduce(callback func(Value) bool) Value + // Reduce iteratively reduces the data to a single value using a callback + // function and returns the result. + // + // The callback function takes two `Value` arguments, the first being the + // carry value from the previous iteration (or the first element for the + // first iteration) and the second being the current element. The callback + // returns a `Value` which becomes the carry value for the next iteration. + // After all iterations, Reduce returns the final carry value. + // + // For a non-empty model, the first element is used as the initial carry, + // so the callback is first invoked with that carry and the second + // element. For an empty model, Reduce returns nil and does not invoke the + // callback. + Reduce(callback func(carry, cur Value) Value) Value // Set stores a value in the internal data store. All values must be // identified by key. Set(key interface{}, value interface{}) error // SetData replaces the current data stored in the model with the // provided data. SetData(data interface{}) error + // Reverse reverses the order of the data store. + Reverse() error // SetID sets this Model's identifier property. - SetID(id interface{}) + // + // It returns an error if the model is read-only (for example, after + // Lock has been called) or if id is invalid or of an unsupported type + // for the implementation. + SetID(id interface{}) error // SetType sets the model type. If any data is stored in this model, // this property becomes read-only. SetType(typ ModelType) error diff --git a/sorter/sorter.go b/sorter/sorter.go index bc77933..fd98967 100644 --- a/sorter/sorter.go +++ b/sorter/sorter.go @@ -1,17 +1,34 @@ package sorter // SortFlag provides a type for sort flags -type SortFlag int +type SortFlag uint const ( - // SortByKey - sort hash data by key - SortByKey SortFlag = iota + // SortByValue - sort data by value using type-stratified comparison: + // nil < bool < numeric < string < other. This is the default/zero value. + SortByValue SortFlag = 0 + + // SortByKey - sort hash data by key. + SortByKey SortFlag = 1 << 0 + + // SortAsc - sort data in ascending order. This is the default. + SortAsc SortFlag = 1 << 1 + + // SortDesc - sort data in descending order. + SortDesc SortFlag = 1 << 2 + + // SortAsString - when sorting data use string comparison via cast. This is + // a tiebreak for SortByValue and the default for SortByKey. + SortAsString SortFlag = 1 << 3 + + // SortReverse - reverse the order of the data set after sorting. + SortReverse SortFlag = 1 << 4 ) // Sorter describes a sorter. type Sorter interface { // Reverse reverses the order of the data set. - Reverse(SortFlag) error + Reverse() error // Sort sorts the model data. Sort(SortFlag) error // Len returns the number of items stored in this model.