Skip to content

Commit fe1142f

Browse files
author
Paddy Carver
committed
Consolidate our handling of JSON types.
We had two separate implementations of JSON type parsing, and that just seems wasteful. One was similar to cty's, and used a custom JSON decoder to parse types. One was a novel algorithm that decoded the JSON bytes into an `interface{}` and read the resulting Go types using a switch statement to understand the type information. This consolidates to only use the cty-esque implementation, which is presumably more accurate and stable.
1 parent 01eb778 commit fe1142f

File tree

5 files changed

+111
-214
lines changed

5 files changed

+111
-214
lines changed

tfprotov5/dynamic_value_json.go

Lines changed: 1 addition & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package tfprotov5
33
import (
44
"bytes"
55
"encoding/json"
6-
"fmt"
76

87
"github.com/hashicorp/terraform-plugin-go/tfprotov5/tftypes"
98
)
@@ -127,7 +126,7 @@ func jsonUnmarshalDynamicPseudoType(buf []byte, typ tftypes.Type, p tftypes.Attr
127126
}
128127
switch key {
129128
case "type":
130-
t, err = parseJSONType(rawVal)
129+
t, err = tftypes.ParseJSONType(rawVal)
131130
if err != nil {
132131
return tftypes.Value{}, p.NewErrorf("error decoding type information: %w", err)
133132
}
@@ -432,129 +431,3 @@ func jsonUnmarshalObject(buf []byte, attrTypes map[string]tftypes.Type, p tftype
432431
AttributeTypes: attrTypes,
433432
}, vals), nil
434433
}
435-
436-
type jsonType struct {
437-
t tftypes.Type
438-
}
439-
440-
func parseJSONType(buf []byte) (tftypes.Type, error) {
441-
var t jsonType
442-
err := json.Unmarshal(buf, &t)
443-
return t.t, err
444-
}
445-
446-
func (t *jsonType) UnmarshalJSON(buf []byte) error {
447-
r := bytes.NewReader(buf)
448-
dec := json.NewDecoder(r)
449-
450-
tok, err := dec.Token()
451-
if err != nil {
452-
return err
453-
}
454-
455-
switch v := tok.(type) {
456-
case string:
457-
switch v {
458-
case "bool":
459-
t.t = tftypes.Bool
460-
case "number":
461-
t.t = tftypes.Number
462-
case "string":
463-
t.t = tftypes.String
464-
case "dynamic":
465-
t.t = tftypes.DynamicPseudoType
466-
default:
467-
return fmt.Errorf("invalid primitive type name %q", v)
468-
}
469-
470-
if dec.More() {
471-
return fmt.Errorf("extraneous data after type description")
472-
}
473-
return nil
474-
case json.Delim:
475-
if rune(v) != '[' {
476-
return fmt.Errorf("invalid complex type description")
477-
}
478-
479-
tok, err = dec.Token()
480-
if err != nil {
481-
return err
482-
}
483-
484-
kind, ok := tok.(string)
485-
if !ok {
486-
return fmt.Errorf("invalid complex type kind name")
487-
}
488-
489-
switch kind {
490-
case "list":
491-
var ety jsonType
492-
err = dec.Decode(&ety)
493-
if err != nil {
494-
return err
495-
}
496-
t.t = tftypes.List{
497-
ElementType: ety.t,
498-
}
499-
case "map":
500-
var ety jsonType
501-
err = dec.Decode(&ety)
502-
if err != nil {
503-
return err
504-
}
505-
t.t = tftypes.Map{
506-
AttributeType: ety.t,
507-
}
508-
case "set":
509-
var ety jsonType
510-
err = dec.Decode(&ety)
511-
if err != nil {
512-
return err
513-
}
514-
t.t = tftypes.Set{
515-
ElementType: ety.t,
516-
}
517-
case "object":
518-
var atys map[string]jsonType
519-
err = dec.Decode(&atys)
520-
if err != nil {
521-
return err
522-
}
523-
types := make(map[string]tftypes.Type, len(atys))
524-
for k, v := range atys {
525-
types[k] = v.t
526-
}
527-
t.t = tftypes.Object{
528-
AttributeTypes: types,
529-
}
530-
case "tuple":
531-
var etys []jsonType
532-
err = dec.Decode(&etys)
533-
if err != nil {
534-
return err
535-
}
536-
types := make([]tftypes.Type, 0, len(etys))
537-
for _, ty := range etys {
538-
types = append(types, ty.t)
539-
}
540-
t.t = tftypes.Tuple{
541-
ElementTypes: types,
542-
}
543-
default:
544-
return fmt.Errorf("invalid complex type kind name")
545-
}
546-
547-
tok, err = dec.Token()
548-
if err != nil {
549-
return err
550-
}
551-
if delim, ok := tok.(json.Delim); !ok || rune(delim) != ']' || dec.More() {
552-
return fmt.Errorf("unexpected extra data in type description")
553-
}
554-
555-
return nil
556-
557-
default:
558-
return fmt.Errorf("invalid type description")
559-
}
560-
}

tfprotov5/dynamic_value_msgpack.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,7 @@ func msgpackUnmarshalDynamic(dec *msgpack.Decoder, path tftypes.AttributePath) (
306306
if err != nil {
307307
return tftypes.Value{}, path.NewErrorf("error decoding bytes: %w", err)
308308
}
309-
typ, err := parseJSONType(typeJSON)
309+
typ, err := tftypes.ParseJSONType(typeJSON)
310310
if err != nil {
311311
return tftypes.Value{}, path.NewErrorf("error parsing type information: %w", err)
312312
}

tfprotov5/internal/fromproto/schema.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55

66
"github.com/hashicorp/terraform-plugin-go/tfprotov5"
77
"github.com/hashicorp/terraform-plugin-go/tfprotov5/internal/tfplugin5"
8+
"github.com/hashicorp/terraform-plugin-go/tfprotov5/tftypes"
89
)
910

1011
func Schema(in *tfplugin5.Schema) (*tfprotov5.Schema, error) {
@@ -51,7 +52,7 @@ func SchemaAttribute(in *tfplugin5.Schema_Attribute) (*tfprotov5.SchemaAttribute
5152
DescriptionKind: StringKind(in.DescriptionKind),
5253
Deprecated: in.Deprecated,
5354
}
54-
typ, err := TerraformTypesType(in.Type)
55+
typ, err := tftypes.ParseJSONType(in.Type)
5556
if err != nil {
5657
return resp, err
5758
}
Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,8 @@
11
package fromproto
22

33
import (
4-
"encoding/json"
5-
"fmt"
6-
74
"github.com/hashicorp/terraform-plugin-go/tfprotov5"
85
"github.com/hashicorp/terraform-plugin-go/tfprotov5/internal/tfplugin5"
9-
"github.com/hashicorp/terraform-plugin-go/tfprotov5/tftypes"
106
)
117

128
func DynamicValue(in *tfplugin5.DynamicValue) *tfprotov5.DynamicValue {
@@ -15,12 +11,3 @@ func DynamicValue(in *tfplugin5.DynamicValue) *tfprotov5.DynamicValue {
1511
JSON: in.Json,
1612
}
1713
}
18-
19-
func TerraformTypesType(in []byte) (tftypes.Type, error) {
20-
var raw interface{}
21-
err := json.Unmarshal(in, &raw)
22-
if err != nil {
23-
return nil, fmt.Errorf("error parsing type, not valid JSON: %w", err)
24-
}
25-
return tftypes.ParseType(raw)
26-
}

0 commit comments

Comments
 (0)