mirror of
https://github.com/letic/terraform-provider-google.git
synced 2024-09-19 09:39:59 +00:00
961c878e0d
Switch to using Go modules. This migrates our vendor.json to use Go 1.11's modules system, and replaces the vendor folder with the output of go mod vendor. The vendored code should remain basically the same; I believe some tree shaking of packages and support scripts/licenses/READMEs/etc. happened. This also fixes Travis and our Makefile to no longer use govendor.
94 lines
2.2 KiB
Go
94 lines
2.2 KiB
Go
package stdlib
|
|
|
|
import (
|
|
"encoding/csv"
|
|
"fmt"
|
|
"io"
|
|
"strings"
|
|
|
|
"github.com/zclconf/go-cty/cty"
|
|
"github.com/zclconf/go-cty/cty/function"
|
|
)
|
|
|
|
var CSVDecodeFunc = function.New(&function.Spec{
|
|
Params: []function.Parameter{
|
|
{
|
|
Name: "str",
|
|
Type: cty.String,
|
|
},
|
|
},
|
|
Type: func(args []cty.Value) (cty.Type, error) {
|
|
str := args[0]
|
|
if !str.IsKnown() {
|
|
return cty.DynamicPseudoType, nil
|
|
}
|
|
|
|
r := strings.NewReader(str.AsString())
|
|
cr := csv.NewReader(r)
|
|
headers, err := cr.Read()
|
|
if err == io.EOF {
|
|
return cty.DynamicPseudoType, fmt.Errorf("missing header line")
|
|
}
|
|
if err != nil {
|
|
return cty.DynamicPseudoType, err
|
|
}
|
|
|
|
atys := make(map[string]cty.Type, len(headers))
|
|
for _, name := range headers {
|
|
if _, exists := atys[name]; exists {
|
|
return cty.DynamicPseudoType, fmt.Errorf("duplicate column name %q", name)
|
|
}
|
|
atys[name] = cty.String
|
|
}
|
|
return cty.List(cty.Object(atys)), nil
|
|
},
|
|
Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
|
|
ety := retType.ElementType()
|
|
atys := ety.AttributeTypes()
|
|
str := args[0]
|
|
r := strings.NewReader(str.AsString())
|
|
cr := csv.NewReader(r)
|
|
cr.FieldsPerRecord = len(atys)
|
|
|
|
// Read the header row first, since that'll tell us which indices
|
|
// map to which attribute names.
|
|
headers, err := cr.Read()
|
|
if err != nil {
|
|
return cty.DynamicVal, err
|
|
}
|
|
|
|
var rows []cty.Value
|
|
for {
|
|
cols, err := cr.Read()
|
|
if err == io.EOF {
|
|
break
|
|
}
|
|
if err != nil {
|
|
return cty.DynamicVal, err
|
|
}
|
|
|
|
vals := make(map[string]cty.Value, len(cols))
|
|
for i, str := range cols {
|
|
name := headers[i]
|
|
vals[name] = cty.StringVal(str)
|
|
}
|
|
rows = append(rows, cty.ObjectVal(vals))
|
|
}
|
|
|
|
if len(rows) == 0 {
|
|
return cty.ListValEmpty(ety), nil
|
|
}
|
|
return cty.ListVal(rows), nil
|
|
},
|
|
})
|
|
|
|
// CSVDecode parses the given CSV (RFC 4180) string and, if it is valid,
|
|
// returns a list of objects representing the rows.
|
|
//
|
|
// The result is always a list of some object type. The first row of the
|
|
// input is used to determine the object attributes, and subsequent rows
|
|
// determine the values of those attributes.
|
|
func CSVDecode(str cty.Value) (cty.Value, error) {
|
|
return CSVDecodeFunc.Call([]cty.Value{str})
|
|
}
|