func (s *State) FromFutureTerraform() bool {
	s.Lock()
	defer s.Unlock()
	if s.TFVersion == "" {
		return false
	}
	v := version.Must(version.NewVersion(s.TFVersion))
	return SemVersion.LessThan(v)
}
FromFutureTerraform checks if this state was written by a Terraform
version from the future.
package terraform
import (
	"bufio"
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"reflect"
	"regexp"
	"sort"
	"strconv"
	"strings"
	"sync"
	"github.com/hashicorp/go-multierror"
	"github.com/hashicorp/go-version"
	"github.com/hashicorp/terraform/config"
	"github.com/mitchellh/copystructure"
	"github.com/satori/go.uuid"
)
const (
	StateVersion = 3
)
var rootModulePath = []string{"root"}
func normalizeModulePath(p []string) []string {
	k := len(rootModulePath)
	if len(p) >= len(rootModulePath) {
		if reflect.DeepEqual(p[:k], rootModulePath) {
			return p
		}
	}
	result := make([]string, len(rootModulePath)+len(p))
	copy(result, rootModulePath)
	copy(result[k:], p)
	return result
}
type State struct {
	Version int `json:"version"`
	TFVersion string `json:"terraform_version,omitempty"`
	Serial int64 `json:"serial"`
	Lineage string `json:"lineage"`
	Remote *RemoteState `json:"remote,omitempty"`
	Backend *BackendState `json:"backend,omitempty"`
	Modules []*ModuleState `json:"modules"`
	mu sync.Mutex
}
func (s *State) Lock()   { s.mu.Lock() }
func (s *State) Unlock() { s.mu.Unlock() }
func NewState() *State {
	s := &State{}
	s.init()
	return s
}
func (s *State) Children(path []string) []*ModuleState {
	s.Lock()
	defer s.Unlock()
	return s.children(path)
}
func (s *State) children(path []string) []*ModuleState {
	result := make([]*ModuleState, 0)
	for _, m := range s.Modules {
		if m == nil {
			continue
		}
		if len(m.Path) != len(path)+1 {
			continue
		}
		if !reflect.DeepEqual(path, m.Path[:len(path)]) {
			continue
		}
		result = append(result, m)
	}
	return result
}
func (s *State) AddModule(path []string) *ModuleState {
	s.Lock()
	defer s.Unlock()
	return s.addModule(path)
}
func (s *State) addModule(path []string) *ModuleState {
	m := s.moduleByPath(path)
	if m != nil {
		return m
	}
	m = &ModuleState{Path: path}
	m.init()
	s.Modules = append(s.Modules, m)
	s.sort()
	return m
}
func (s *State) ModuleByPath(path []string) *ModuleState {
	if s == nil {
		return nil
	}
	s.Lock()
	defer s.Unlock()
	return s.moduleByPath(path)
}
func (s *State) moduleByPath(path []string) *ModuleState {
	for _, mod := range s.Modules {
		if mod == nil {
			continue
		}
		if mod.Path == nil {
			panic("missing module path")
		}
		if reflect.DeepEqual(mod.Path, path) {
			return mod
		}
	}
	return nil
}
func (s *State) ModuleOrphans(path []string, c *config.Config) [][]string {
	s.Lock()
	defer s.Unlock()
	return s.moduleOrphans(path, c)
}
func (s *State) moduleOrphans(path []string, c *config.Config) [][]string {
	direct := make(map[string]struct{})
	childrenKeys := make(map[string]struct{})
	if c != nil {
		for _, m := range c.Modules {
			childrenKeys[m.Name] = struct{}{}
			direct[m.Name] = struct{}{}
		}
	}
	var orphans [][]string
	for _, m := range s.children(path) {
		key := m.Path[len(m.Path)-1]
		direct[key] = struct{}{}
		if _, ok := childrenKeys[key]; ok {
			continue
		}
		orphans = append(orphans, m.Path)
	}
	for _, m := range s.Modules {
		if m == nil {
			continue
		}
		if len(m.Path) < len(path)+2 {
			continue
		}
		if !reflect.DeepEqual(path, m.Path[:len(path)]) {
			continue
		}
		key := m.Path[len(path)]
		if _, ok := direct[key]; ok {
			continue
		}
		orphanPath := m.Path[:len(path)+1]
		alreadyAdded := false
		for _, o := range orphans {
			if reflect.DeepEqual(o, orphanPath) {
				alreadyAdded = true
				break
			}
		}
		if alreadyAdded {
			continue
		}
		orphans = append(orphans, orphanPath)
	}
	return orphans
}
func (s *State) Empty() bool {
	if s == nil {
		return true
	}
	s.Lock()
	defer s.Unlock()
	return len(s.Modules) == 0
}
func (s *State) HasResources() bool {
	if s.Empty() {
		return false
	}
	for _, mod := range s.Modules {
		if len(mod.Resources) > 0 {
			return true
		}
	}
	return false
}
func (s *State) IsRemote() bool {
	if s == nil {
		return false
	}
	s.Lock()
	defer s.Unlock()
	if s.Remote == nil {
		return false
	}
	if s.Remote.Type == "" {
		return false
	}
	return true
}
func (s *State) Validate() error {
	s.Lock()
	defer s.Unlock()
	var result error
	{
		found := make(map[string]struct{})
		for _, ms := range s.Modules {
			if ms == nil {
				continue
			}
			key := strings.Join(ms.Path, ".")
			if _, ok := found[key]; ok {
				result = multierror.Append(result, fmt.Errorf(
					strings.TrimSpace(stateValidateErrMultiModule), key))
				continue
			}
			found[key] = struct{}{}
		}
	}
	return result
}
func (s *State) Remove(addr ...string) error {
	s.Lock()
	defer s.Unlock()
	filter := &StateFilter{State: s}
	results, err := filter.Filter(addr...)
	if err != nil {
		return err
	}
	if len(results) == 0 {
		return nil
	}
	removed := make(map[interface{}]struct{})
	for _, r := range results {
		path := append([]string{"root"}, r.Path...)
		if _, ok := removed[r.Value]; ok {
			continue
		}
		if r.Parent != nil {
			if _, ok := removed[r.Parent.Value]; ok {
				continue
			}
		}
		removed[r.Value] = struct{}{}
		switch v := r.Value.(type) {
		case *ModuleState:
			s.removeModule(path, v)
		case *ResourceState:
			s.removeResource(path, v)
		case *InstanceState:
			s.removeInstance(path, r.Parent.Value.(*ResourceState), v)
		default:
			return fmt.Errorf("unknown type to delete: %T", r.Value)
		}
	}
	s.prune()
	return nil
}
func (s *State) removeModule(path []string, v *ModuleState) {
	for i, m := range s.Modules {
		if m == v {
			s.Modules, s.Modules[len(s.Modules)-1] = append(s.Modules[:i], s.Modules[i+1:]...), nil
			return
		}
	}
}
func (s *State) removeResource(path []string, v *ResourceState) {
	mod := s.moduleByPath(path)
	if mod == nil {
		return
	}
	for k, r := range mod.Resources {
		if r == v {
			delete(mod.Resources, k)
			return
		}
	}
}
func (s *State) removeInstance(path []string, r *ResourceState, v *InstanceState) {
	if r.Primary == v {
		r.Primary = nil
		return
	}
	lists := [][]*InstanceState{r.Deposed}
	for _, is := range lists {
		for i, instance := range is {
			if instance == v {
				is, is[len(is)-1] = append(is[:i], is[i+1:]...), nil
				return
			}
		}
	}
}
func (s *State) RootModule() *ModuleState {
	root := s.ModuleByPath(rootModulePath)
	if root == nil {
		panic("missing root module")
	}
	return root
}
func (s *State) Equal(other *State) bool {
	if s == nil || other == nil {
		return s == other
	}
	s.Lock()
	defer s.Unlock()
	return s.equal(other)
}
func (s *State) equal(other *State) bool {
	if s == nil || other == nil {
		return s == other
	}
	if s.Version != other.Version {
		return false
	}
	if len(s.Modules) != len(other.Modules) {
		return false
	}
	for _, m := range s.Modules {
		otherM := other.moduleByPath(m.Path)
		if otherM == nil {
			return false
		}
		if !m.Equal(otherM) {
			return false
		}
	}
	return true
}
type StateAgeComparison int
const (
	StateAgeEqual         StateAgeComparison = 0
	StateAgeReceiverNewer StateAgeComparison = 1
	StateAgeReceiverOlder StateAgeComparison = -1
)
func (s *State) CompareAges(other *State) (StateAgeComparison, error) {
	switch {
	case s != nil && other == nil:
		return StateAgeReceiverNewer, nil
	case s == nil && other != nil:
		return StateAgeReceiverOlder, nil
	case s == nil && other == nil:
		return StateAgeEqual, nil
	}
	if !s.SameLineage(other) {
		return StateAgeEqual, fmt.Errorf(
			"can't compare two states of differing lineage",
		)
	}
	s.Lock()
	defer s.Unlock()
	switch {
	case s.Serial < other.Serial:
		return StateAgeReceiverOlder, nil
	case s.Serial > other.Serial:
		return StateAgeReceiverNewer, nil
	default:
		return StateAgeEqual, nil
	}
}
func (s *State) SameLineage(other *State) bool {
	s.Lock()
	defer s.Unlock()
	if s.Lineage == "" || other.Lineage == "" {
		return true
	}
	return s.Lineage == other.Lineage
}
func (s *State) DeepCopy() *State {
	copy, err := copystructure.Config{Lock: true}.Copy(s)
	if err != nil {
		panic(err)
	}
	return copy.(*State)
}
func (s *State) IncrementSerialMaybe(other *State) {
	if s == nil {
		return
	}
	if other == nil {
		return
	}
	s.Lock()
	defer s.Unlock()
	if s.Serial > other.Serial {
		return
	}
	if other.TFVersion != s.TFVersion || !s.equal(other) {
		if other.Serial > s.Serial {
			s.Serial = other.Serial
		}
		s.Serial++
	}
}