refs

package
v0.0.0-...-917641f Latest Latest
Warning

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

Go to latest
Published: Sep 30, 2019 License: MIT Imports: 1 Imported by: 0

Documentation

Overview

Package refs implements reference paths, carets and selections.

A reference path, caret or selection refers to an item or a position in an array-like object or a set of items in an array-like object. As changes are applied, the path may be affected as well as items that the path refers to. This package provides the mechanism to deal with these.

Index

Constants

This section is empty.

Variables

View Source
var InvalidRef = invalidRef{}

InvalidRef refers to a ref that no longer exists.

Functions

This section is empty.

Types

type Caret

type Caret struct {
	Path
	Index  int
	IsLeft bool
}

Caret is a reference to a specific position in an array-like object.

This is an immutable type

This only handles the standard set of changes. Custom changes should implement a MergeCaret method:

MergeCaret(caret refs.Caret) (refs.Ref)

Note that this is in addition to the MergePath method which is called first to transform the path and then the MergeCaret is called on the updated Caret (based on the path returned by MergePath).

The IsLeft flag controls whether the position sticks with the element to the left in case of insertions happening at the index. The default is for the reference to stick to the element on the right.

func (Caret) Equal

func (caret Caret) Equal(other Ref) bool

Equal impements Ref.Equal

func (Caret) Merge

func (caret Caret) Merge(c changes.Change) (Ref, changes.Change)

Merge updates the caret index based on the change. Note that it always returns a nil change as there is no way for a change to affect the caret.

type Container

type Container struct {
	changes.Value
	// contains filtered or unexported fields
}

Container wraps a Value and a set of references into the value.

It implements the changes.Value interface. It acts like a "map-like" object with the wrapped value taking up the key "Value". The references are not accessed vai PathChange. Instead they are accessed via Update changes only. This allows all changes to be properly merged.

func NewContainer

func NewContainer(v changes.Value, refs map[interface{}]Ref) Container

NewContainer wraps the value and refs into a Container

func (Container) Apply

func (con Container) Apply(ctx changes.Context, c changes.Change) changes.Value

Apply implements changes.Value:Apply

func (Container) GetRef

func (con Container) GetRef(key interface{}) Ref

GetRef returns the current ref for the provided key

func (Container) Refs

func (con Container) Refs() map[interface{}]Ref

Refs returns the internal set of refs associated with the container

func (Container) UpdateRef

func (con Container) UpdateRef(key interface{}, r Ref) (Container, changes.Change)

UpdateRef updates a ref. If r is nil, the reference is deleted. All references should have "Value" as a prefix to the path.

type MergeResult

type MergeResult struct {
	P          []interface{}
	Scoped     changes.Change
	Affected   changes.Change
	Unaffected changes.Change
}

MergeResult contains the result of calling Merge on a path. If the path is invalidated by the change, the whole result is nil. Otherwise the field P specifies the updated path. Affected returns a version of the change that can be applied on the object at the path (and is set to nil if the chagne does not have any local effect). Unaffected contains any changes that do not affect the path. Unaffected+Affected should be the equivalent of the original change.

func Merge

func Merge(p []interface{}, c changes.Change) *MergeResult

Merge merges a path with a change. If the path is invalidated, it returns nil. Otherwise, it returns the updated path. The version of the change that can be applied to the just object at the path itself is in Affected. Unaffected holds the changes that does not concern the provided path.

Custom changes should implement the PathMerger interface or the change will be considered as not affecting the path in any way

For most purposes, the Path type is a better fit than directly calling Merge.

func (*MergeResult) Prefix

func (p *MergeResult) Prefix(other []interface{}) *MergeResult

Prefix updates the merge result to include the prefix to the path. It does not update the Scoped field.

type Path

type Path []interface{}

Path represents a reference to a value at a specific path. A nil or empty path refers to the root value.

This is an immutable type -- none of the methods modify the provided path itself.

This only handles the standard set of changes. Custom changes should implement the PathMerger interface.

If no such method is implemented by the change, the change is ignored as if it has no side-effects.

func (Path) Equal

func (p Path) Equal(other Ref) bool

Equal implements Ref.Equal

func (Path) Merge

func (p Path) Merge(c changes.Change) (Ref, changes.Change)

Merge implements Ref.Merge

type PathMerger

type PathMerger interface {
	MergePath(p []interface{}) *MergeResult
}

PathMerger is the interface that custom Change types should implement.

type Range

type Range struct {
	Start, End Caret
}

Range is a reference to a specific selection of elements in an array-like object. Ranges can be "collapsed" when they behave the same as Caret.

This is an immutable type

This only handles the standard set of changes. Custom changes should implement a MergeCaret method:

MergeCaret(caret refs.Caret) (refs.Ref)

Range is implemented on top of Caret and doing the above is sufficient.

Note that this is in addition to the MergePath method which is called first to transform the path and then the MergeCaret is called on the updated Caret (based on the path returned by MergePath).

Note that the paths for the Start and End are expected to be the same.

func (Range) Equal

func (r Range) Equal(other Ref) bool

Equal implements Ref.Equal

func (Range) Merge

func (r Range) Merge(c changes.Change) (Ref, changes.Change)

Merge updates the range based on the change. Note that it always returns a nil change as there are cases where there isn't sufficient information to return the correct changes.Change.

type Ref

type Ref interface {
	// Merge takes a change and returns an Ref that reflects the
	// effect of the change.  If the change affects the item
	// specified by the Ref, it returns a modified version of the
	// change that can be applied to the value at the Ref.
	Merge(c changes.Change) (Ref, changes.Change)

	// Equal tests if two refs are the same.
	Equal(other Ref) bool
}

Ref represents the core Reference type

type Update

type Update struct {
	Key           interface{}
	Before, After Ref
}

Update implements changes.Change interface. All updates of references at the container level can only be done using this interface. Nil is not a valid value for a ref and as such can be used to indicate the ref didn't exist before or to delete a ref

Unlike most changes, Update is a bit improper. The value of the reference is modified by unrelated changes. For example, deleting of an element can invalidate or modify the path. This has an unfortunate side-effect: Reverts may not restore the references perfectly.

func (Update) ApplyTo

func (u Update) ApplyTo(ctx changes.Context, v changes.Value) changes.Value

ApplyTo implements changes.Custom

func (Update) Merge

func (u Update) Merge(c changes.Change) (cx, ux changes.Change)

Merge implements changes.Change

func (Update) ReverseMerge

func (u Update) ReverseMerge(c changes.Change) (cx, ux changes.Change)

ReverseMerge implements changes.Custom

func (Update) Revert

func (u Update) Revert() changes.Change

Revert implements changes.Change

Jump to

Keyboard shortcuts

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