// Copyright (C) 2018 rameshvk. All rights reserved.
// Use of this source code is governed by a MIT-style license
// that can be found in the LICENSE file.

package types

import "github.com/dotchain/dot/changes"

// Generic is a helper to build value and collection types
type Generic struct {
	Get    func(key interface{}) changes.Value
	Set    func(key interface{}, v changes.Value) changes.Value
	Splice func(offset, count int, insert changes.Collection) changes.Collection
}

// Apply applies a change to produce a new value. Note that this
// requires the current value as input unlike changes.Value.
func (g Generic) Apply(ctx changes.Context, c changes.Change, current changes.Value) changes.Value {
	switch c := c.(type) {
	case nil:
		return current
	case changes.Replace:
		if c.IsDelete() {
			return changes.Nil
		}
		return c.After
	case changes.PathChange:
		if len(c.Path) == 0 {
			return g.Apply(ctx, c.Change, current)
		}
		inner := changes.PathChange{Path: c.Path[1:], Change: c.Change}
		return g.Set(c.Path[0], g.Get(c.Path[0]).Apply(ctx, inner))
	case changes.Splice, changes.Move:
		return g.ApplyCollection(ctx, c, current.(changes.Collection))
	}

	return c.(changes.Custom).ApplyTo(ctx, current)
}

// ApplyCollection implements changes.ApplyCollection but with
// using the provided current value and the helper functions
func (g Generic) ApplyCollection(ctx changes.Context, c changes.Change, current changes.Collection) changes.Collection {
	switch c := c.(type) {
	case changes.Splice:
		return g.Splice(c.Offset, c.Before.Count(), c.After)
	case changes.Move:
		c = c.Normalize()
		slice := current.Slice(c.Offset, c.Count)
		empty := current.Slice(0, 0)
		splice := changes.Splice{Offset: c.Offset + c.Distance, Before: empty, After: slice}
		return g.Splice(c.Offset, c.Count, empty).ApplyCollection(ctx, splice)
	}
	return g.Apply(ctx, c, current).(changes.Collection)
}

Related articles

dot ord

// Copyright (C) 2019 rameshvk. All rights reserved. // Use of this source code is governed by a MIT-style license // that can be found in the LICENSE file. package crdt import ( "math/big" "strconv" "strings" ) // NextOrd returns the next ordinal.

dot heading_test

// Copyright (C) 2019 rameshvk. All rights reserved. // Use of this source code is governed by a MIT-style license // that can be found in the LICENSE file. package data_test import ( "reflect" "testing" "github.com/dotchain/dot/changes" "github.c

dot typename

// Copyright (C) 2018 rameshvk. All rights reserved. // Use of this source code is governed by a MIT-style license // that can be found in the LICENSE file. package sjson import ( "errors" "reflect" "strconv" "strings" "time" ) func typeName(v re

dot go

github.com/etcd-io/bbolt v1.3.2 h1:RLRQ0TKLX7DlBRXAJHvbmXL17Q3KNnTBtZ9B6Qo+/Y0= github.com/etcd-io/bbolt v1.3.2/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ= github.

dot setattr_test

// Copyright (C) 2019 rameshvk. All rights reserved. // Use of this source code is governed by a MIT-style license // that can be found in the LICENSE file. package rich_test import ( "testing" "github.com/dotchain/dot/changes" "github.com/dotchain

dot poller_test

// Copyright (C) 2018 rameshvk. All rights reserved. // Use of this source code is governed by a MIT-style license // that can be found in the LICENSE file. package ops_test import ( "context" "errors" "testing" "time" "github.com/dotchain/dot/op

dot row

// Copyright (C) 2019 rameshvk. All rights reserved. // Use of this source code is governed by a MIT-style license // that can be found in the LICENSE file. package data import ( "github.com/dotchain/dot/changes" "github.com/dotchain/dot/changes/type

dot int_test

// Copyright (C) 2018 rameshvk. All rights reserved. // Use of this source code is governed by a MIT-style license // that can be found in the LICENSE file. package streams_test import ( "reflect" "testing" "github.com/dotchain/dot/changes" "githu

dot request

// Copyright (C) 2018 rameshvk. All rights reserved. // Use of this source code is governed by a MIT-style license // that can be found in the LICENSE file. package nw import ( "bytes" "context" "io" "strconv" "time" "github.com/dotchain/dot/log

dot heap

// Copyright (C) 2018 rameshvk. All rights reserved. // Use of this source code is governed by a MIT-style license // that can be found in the LICENSE file. // Package heap implements a heap value type package heap import ( "math/rand" "sort" "time"