delta

package
v0.38.0 Latest Latest
Warning

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

Go to latest
Published: Aug 29, 2026 License: Apache-2.0 Imports: 5 Imported by: 1

README

delta

Change-tracking containers. delta.Slice[T] wraps a []T and records which elements were Added and Deleted relative to its starting state, so a caller can compute and apply a minimal diff. Part of rosetta.

What matters here

  • Only Values is serialized; Added and Deleted are transient. Both carry json:"-" bson:"-" tags — the diff bookkeeping exists only for the lifetime of the in-memory object and is intentionally not persisted. A round-trip through JSON/BSON yields a Slice with the current values but an empty change set, as if freshly constructed.
  • SetValue(any) is the schema-integration seam (it satisfies the ValueSetter interface used by schema). It accepts a generic value and coerces it into []T; that is why the element type is constrained to comparable (membership checks drive the Added/Deleted tracking).
  • SetValue must never assume it is handed a []T. Multi-value form widgets (multiselect, check-button-group) post a *sliceof.String, because that is the only shape satisfying the ArrayGetterSetter validation that schema.validate_Array requires. Conversion is delegated to convert.SliceOfOk[T], which unwraps pointers, named slice types, and convert.ArrayGetter values; a strict type assertion here silently discarded every multiselect write for six weeks.
  • Conversion is as loose as the convert package allows, including LOSSY. SetValue discards convert's lossless flag, so Slice[string] handed 3.14159 stores ["3.14"]. The flip side: a Slice[int] handed "not a number" stores [0] rather than erroring. Only a value that is not a collection at all — a struct, a map, a channel — is an error, checked up front with convert.SliceOfAnyOk so that a rejected write cannot empty Values and fill Deleted.
  • A value that cannot be read leaves the Slice untouched. Coercion completes before any state is written, so a failed SetValue cannot empty Values and fill Deleted — which would read downstream as "the user removed everything."
  • Values is copied, not aliased. The incoming slice arrives straight from a url.Values entry that the caller still owns.
  • UnmarshalJSON parses untrusted input and is fuzzed (FuzzSliceUnmarshalJSON). When changing the unmarshal path, keep that fuzzer green — it guards against panics on malformed JSON.

Documentation

Overview

Package delta provides collection types that track their own changes.

A delta.Slice[T] wraps an ordinary []T and records which elements have been added and which have been deleted relative to the values it started with, so a caller can compute a minimal diff and apply only what actually moved. The element type is constrained to comparable because membership checks are what drive that bookkeeping.

Only the values are serialized. The Added and Deleted sets are marked json:"-" and bson:"-" on purpose: they describe one in-memory editing session, not durable state, so a value that round-trips through storage comes back with its current contents and an empty change set.

SetValue is the seam that the schema package writes through, and it converts whatever it is handed rather than asserting a []T: form widgets deliver array values as a *sliceof.String, and several other shapes are possible besides. The conversion is delegated to convert.SliceOfOk, so it is as forgiving as that package allows -- lossy renderings included -- and only a value that is not a collection at all is reported, without disturbing the slice.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Slice

type Slice[T comparable] struct {
	Values  []T `json:"values" bson:"values"`
	Added   []T `json:"-"      bson:"-"`
	Deleted []T `json:"-"      bson:"-"`
}

Slice tracks changes to a slice of generic values. As items are added or removed from the slice, they are tracked in the "Added" and "Deleted" lists.

func NewSlice

func NewSlice[T comparable](values ...T) Slice[T]

NewSlice returns a fully initialized Slice object

func (Slice[T]) GetIndex added in v0.29.0

func (s Slice[T]) GetIndex(index int) (any, bool)

GetIndex implements schema.ArrayGetter, returning the value at the provided index and TRUE, or (nil, false) if the index is out of range.

func (Slice[T]) GetValue

func (s Slice[T]) GetValue() any

GetValue implements schema.ValueGetter and returns the current value

func (Slice[T]) IsChanged

func (s Slice[T]) IsChanged() bool

IsChanged returns TRUE if the slice has been modified

func (Slice[T]) Length

func (s Slice[T]) Length() int

Length returns the number of keys in the map

func (Slice[T]) MarshalJSON

func (s Slice[T]) MarshalJSON() ([]byte, error)

MarshalJSON implements the json.Marshaler interface and serializes the Slice into a JSON array

func (*Slice[T]) Reset

func (s *Slice[T]) Reset()

Reset resets all of the added/deleted values

func (*Slice[T]) SetIndex added in v0.29.0

func (s *Slice[T]) SetIndex(index int, value any) bool

SetIndex implements schema.ArraySetter, storing a value at the provided index (growing the slice to fit if necessary) and tracking any newly-added value. Returns FALSE if the value is not assignable to the slice's element type.

func (*Slice[T]) SetValue

func (s *Slice[T]) SetValue(value any) error

SetValue implements schema.ValueSetter and updates the current value, tracking changes to the added and deleted lists.

func (Slice[T]) Unchanged added in v0.25.4

func (s Slice[T]) Unchanged() []T

Unchanged returns the values that have not been added or removed

func (*Slice[T]) UnmarshalJSON

func (s *Slice[T]) UnmarshalJSON(data []byte) error

UnmarshalJSON implements the json.Unmarshaler interface and deserializes the Slice from a JSON array

Jump to

Keyboard shortcuts

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