func (d *ResourceDiff) SetNew(key string, value interface{}) error {
	if err := d.checkKey(key, "SetNew", false); err != nil {
		return err
	}
	return d.setDiff(key, value, false)
}
SetNew is used to set a new diff value for the mentioned key. The value must
be correct for the attribute's schema (mostly relevant for maps, lists, and
sets). The original value from the state is used as the old value.

This function is only allowed on computed attributes.
package schema
import (
	"errors"
	"fmt"
	"reflect"
	"strings"
	"sync"
	"github.com/hashicorp/terraform/terraform"
)
type newValueWriter struct {
	*MapFieldWriter
	computedKeys map[string]bool
	lock sync.Mutex
	once sync.Once
}
func (w *newValueWriter) init() {
	if w.computedKeys == nil {
		w.computedKeys = make(map[string]bool)
	}
}
func (w *newValueWriter) WriteField(address []string, value interface{}, computed bool) error {
	if value != nil && computed {
		return errors.New("Non-nil value with computed set")
	}
	if err := w.MapFieldWriter.WriteField(address, value); err != nil {
		return err
	}
	w.once.Do(w.init)
	w.lock.Lock()
	defer w.lock.Unlock()
	if computed {
		w.computedKeys[strings.Join(address, ".")] = true
	}
	return nil
}
func (w *newValueWriter) ComputedKeysMap() map[string]bool {
	w.once.Do(w.init)
	return w.computedKeys
}
type newValueReader struct {
	*MapFieldReader
	computedKeys map[string]bool
}
func (r *newValueReader) ReadField(address []string) (FieldReadResult, error) {
	addrKey := strings.Join(address, ".")
	v, err := r.MapFieldReader.ReadField(address)
	if err != nil {
		return FieldReadResult{}, err
	}
	for computedKey := range r.computedKeys {
		if childAddrOf(addrKey, computedKey) {
			if strings.HasSuffix(addrKey, ".#") {
				v.Exists = false
			}
			v.Computed = true
		}
	}
	return v, nil
}
type ResourceDiff struct {
	schema map[string]*Schema
	config *terraform.ResourceConfig
	state *terraform.InstanceState
	diff *terraform.InstanceDiff
	multiReader *MultiLevelFieldReader
	newWriter *newValueWriter
	updatedKeys map[string]bool
	forcedNewKeys map[string]bool
}
func newResourceDiff(schema map[string]*Schema, config *terraform.ResourceConfig, state *terraform.InstanceState, diff *terraform.InstanceDiff) *ResourceDiff {
	d := &ResourceDiff{
		config: config,
		state:  state,
		diff:   diff,
		schema: schema,
	}
	d.newWriter = &newValueWriter{
		MapFieldWriter: &MapFieldWriter{Schema: d.schema},
	}
	readers := make(map[string]FieldReader)
	var stateAttributes map[string]string
	if d.state != nil {
		stateAttributes = d.state.Attributes
		readers["state"] = &MapFieldReader{
			Schema: d.schema,
			Map:    BasicMapReader(stateAttributes),
		}
	}
	if d.config != nil {
		readers["config"] = &ConfigFieldReader{
			Schema: d.schema,
			Config: d.config,
		}
	}
	if d.diff != nil {
		readers["diff"] = &DiffFieldReader{
			Schema: d.schema,
			Diff:   d.diff,
			Source: &MultiLevelFieldReader{
				Levels:  []string{"state", "config"},
				Readers: readers,
			},
		}
	}
	readers["newDiff"] = &newValueReader{
		MapFieldReader: &MapFieldReader{
			Schema: d.schema,
			Map:    BasicMapReader(d.newWriter.Map()),
		},
		computedKeys: d.newWriter.ComputedKeysMap(),
	}
	d.multiReader = &MultiLevelFieldReader{
		Levels: []string{
			"state",
			"config",
			"diff",
			"newDiff",
		},
		Readers: readers,
	}
	d.updatedKeys = make(map[string]bool)
	d.forcedNewKeys = make(map[string]bool)
	return d
}
func (d *ResourceDiff) UpdatedKeys() []string {
	var s []string
	for k := range d.updatedKeys {
		s = append(s, k)
	}
	for k := range d.forcedNewKeys {
		for _, l := range s {
			if k == l {
				break
			}
		}
		s = append(s, k)
	}
	return s
}
func (d *ResourceDiff) Clear(key string) error {
	if err := d.checkKey(key, "Clear", true); err != nil {
		return err
	}
	return d.clear(key)
}
func (d *ResourceDiff) clear(key string) error {
	schemaL := addrToSchema(strings.Split(key, "."), d.schema)
	if len(schemaL) == 0 {
		return fmt.Errorf("%s is not a valid key", key)
	}
	for k := range d.diff.Attributes {
		if strings.HasPrefix(k, key) {
			delete(d.diff.Attributes, k)
		}
	}
	return nil
}
func (d *ResourceDiff) GetChangedKeysPrefix(prefix string) []string {
	keys := make([]string, 0)
	for k := range d.diff.Attributes {
		if strings.HasPrefix(k, prefix) {
			keys = append(keys, k)
		}
	}
	return keys
}
func (d *ResourceDiff) diffChange(key string) (interface{}, interface{}, bool, bool, bool) {
	old, new, customized := d.getChange(key)
	if !old.Exists {
		old.Value = nil
	}
	if !new.Exists || d.removed(key) {
		new.Value = nil
	}
	return old.Value, new.Value, !reflect.DeepEqual(old.Value, new.Value), new.Computed, customized
}