terraform-provider-gitea/vendor/github.com/hashicorp/terraform-json/expression.go
dependabot[bot] 910ccdb092
Bump github.com/hashicorp/terraform-plugin-sdk/v2 from 2.26.1 to 2.27.0
Bumps [github.com/hashicorp/terraform-plugin-sdk/v2](https://github.com/hashicorp/terraform-plugin-sdk) from 2.26.1 to 2.27.0.
- [Release notes](https://github.com/hashicorp/terraform-plugin-sdk/releases)
- [Changelog](https://github.com/hashicorp/terraform-plugin-sdk/blob/main/CHANGELOG.md)
- [Commits](https://github.com/hashicorp/terraform-plugin-sdk/compare/v2.26.1...v2.27.0)

---
updated-dependencies:
- dependency-name: github.com/hashicorp/terraform-plugin-sdk/v2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-03 20:21:30 +00:00

131 lines
3.8 KiB
Go

// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
package tfjson
import "encoding/json"
type unknownConstantValue struct{}
// UnknownConstantValue is a singleton type that denotes that a
// constant value is explicitly unknown. This is set during an
// unmarshal when references are found in an expression to help more
// explicitly differentiate between an explicit null and unknown
// value.
var UnknownConstantValue = &unknownConstantValue{}
// Expression describes the format for an individual key in a
// Terraform configuration.
//
// This struct wraps ExpressionData to support custom JSON parsing.
type Expression struct {
*ExpressionData
}
// ExpressionData describes the format for an individual key in a
// Terraform configuration.
type ExpressionData struct {
// If the *entire* expression is a constant-defined value, this
// will contain the Go representation of the expression's data.
//
// Note that a nil here denotes and explicit null. When a value is
// unknown on part of the value coming from an expression that
// cannot be resolved at parse time, this field will contain
// UnknownConstantValue.
ConstantValue interface{} `json:"constant_value,omitempty"`
// If any part of the expression contained values that were not
// able to be resolved at parse-time, this will contain a list of
// the referenced identifiers that caused the value to be unknown.
References []string `json:"references,omitempty"`
// A list of complex objects that were nested in this expression.
// If this value is a nested block in configuration, sometimes
// referred to as a "sub-resource", this field will contain those
// values, and ConstantValue and References will be blank.
NestedBlocks []map[string]*Expression `json:"-"`
}
// UnmarshalJSON implements json.Unmarshaler for Expression.
func (e *Expression) UnmarshalJSON(b []byte) error {
result := new(ExpressionData)
// Check to see if this is an array first. If it is, this is more
// than likely a list of nested blocks.
var rawNested []map[string]json.RawMessage
if err := json.Unmarshal(b, &rawNested); err == nil {
result.NestedBlocks, err = unmarshalExpressionBlocks(rawNested)
if err != nil {
return err
}
} else {
// It's a non-nested expression block, parse normally
if err := json.Unmarshal(b, &result); err != nil {
return err
}
// If References is non-zero, then ConstantValue is unknown. Set
// this explicitly.
if len(result.References) > 0 {
result.ConstantValue = UnknownConstantValue
}
}
e.ExpressionData = result
return nil
}
func unmarshalExpressionBlocks(raw []map[string]json.RawMessage) ([]map[string]*Expression, error) {
var result []map[string]*Expression
for _, rawBlock := range raw {
block := make(map[string]*Expression)
for k, rawExpr := range rawBlock {
var expr *Expression
if err := json.Unmarshal(rawExpr, &expr); err != nil {
return nil, err
}
block[k] = expr
}
result = append(result, block)
}
return result, nil
}
// MarshalJSON implements json.Marshaler for Expression.
func (e *Expression) MarshalJSON() ([]byte, error) {
switch {
case len(e.ExpressionData.NestedBlocks) > 0:
return marshalExpressionBlocks(e.ExpressionData.NestedBlocks)
case e.ExpressionData.ConstantValue == UnknownConstantValue:
return json.Marshal(&ExpressionData{
References: e.ExpressionData.References,
})
}
return json.Marshal(e.ExpressionData)
}
func marshalExpressionBlocks(nested []map[string]*Expression) ([]byte, error) {
var rawNested []map[string]json.RawMessage
for _, block := range nested {
rawBlock := make(map[string]json.RawMessage)
for k, expr := range block {
raw, err := json.Marshal(expr)
if err != nil {
return nil, err
}
rawBlock[k] = raw
}
rawNested = append(rawNested, rawBlock)
}
return json.Marshal(rawNested)
}