diff options
Diffstat (limited to 'vendor/github.com/hashicorp/hcl2/hcl/json/public.go')
-rw-r--r-- | vendor/github.com/hashicorp/hcl2/hcl/json/public.go | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/vendor/github.com/hashicorp/hcl2/hcl/json/public.go b/vendor/github.com/hashicorp/hcl2/hcl/json/public.go new file mode 100644 index 0000000..2728aa1 --- /dev/null +++ b/vendor/github.com/hashicorp/hcl2/hcl/json/public.go | |||
@@ -0,0 +1,94 @@ | |||
1 | package json | ||
2 | |||
3 | import ( | ||
4 | "fmt" | ||
5 | "io/ioutil" | ||
6 | "os" | ||
7 | |||
8 | "github.com/hashicorp/hcl2/hcl" | ||
9 | ) | ||
10 | |||
11 | // Parse attempts to parse the given buffer as JSON and, if successful, returns | ||
12 | // a hcl.File for the HCL configuration represented by it. | ||
13 | // | ||
14 | // This is not a generic JSON parser. Instead, it deals only with the profile | ||
15 | // of JSON used to express HCL configuration. | ||
16 | // | ||
17 | // The returned file is valid only if the returned diagnostics returns false | ||
18 | // from its HasErrors method. If HasErrors returns true, the file represents | ||
19 | // the subset of data that was able to be parsed, which may be none. | ||
20 | func Parse(src []byte, filename string) (*hcl.File, hcl.Diagnostics) { | ||
21 | rootNode, diags := parseFileContent(src, filename) | ||
22 | |||
23 | switch rootNode.(type) { | ||
24 | case *objectVal, *arrayVal: | ||
25 | // okay | ||
26 | default: | ||
27 | diags = diags.Append(&hcl.Diagnostic{ | ||
28 | Severity: hcl.DiagError, | ||
29 | Summary: "Root value must be object", | ||
30 | Detail: "The root value in a JSON-based configuration must be either a JSON object or a JSON array of objects.", | ||
31 | Subject: rootNode.StartRange().Ptr(), | ||
32 | }) | ||
33 | |||
34 | // Since we've already produced an error message for this being | ||
35 | // invalid, we'll return an empty placeholder here so that trying to | ||
36 | // extract content from our root body won't produce a redundant | ||
37 | // error saying the same thing again in more general terms. | ||
38 | fakePos := hcl.Pos{ | ||
39 | Byte: 0, | ||
40 | Line: 1, | ||
41 | Column: 1, | ||
42 | } | ||
43 | fakeRange := hcl.Range{ | ||
44 | Filename: filename, | ||
45 | Start: fakePos, | ||
46 | End: fakePos, | ||
47 | } | ||
48 | rootNode = &objectVal{ | ||
49 | Attrs: []*objectAttr{}, | ||
50 | SrcRange: fakeRange, | ||
51 | OpenRange: fakeRange, | ||
52 | } | ||
53 | } | ||
54 | |||
55 | file := &hcl.File{ | ||
56 | Body: &body{ | ||
57 | val: rootNode, | ||
58 | }, | ||
59 | Bytes: src, | ||
60 | Nav: navigation{rootNode}, | ||
61 | } | ||
62 | return file, diags | ||
63 | } | ||
64 | |||
65 | // ParseFile is a convenience wrapper around Parse that first attempts to load | ||
66 | // data from the given filename, passing the result to Parse if successful. | ||
67 | // | ||
68 | // If the file cannot be read, an error diagnostic with nil context is returned. | ||
69 | func ParseFile(filename string) (*hcl.File, hcl.Diagnostics) { | ||
70 | f, err := os.Open(filename) | ||
71 | if err != nil { | ||
72 | return nil, hcl.Diagnostics{ | ||
73 | { | ||
74 | Severity: hcl.DiagError, | ||
75 | Summary: "Failed to open file", | ||
76 | Detail: fmt.Sprintf("The file %q could not be opened.", filename), | ||
77 | }, | ||
78 | } | ||
79 | } | ||
80 | defer f.Close() | ||
81 | |||
82 | src, err := ioutil.ReadAll(f) | ||
83 | if err != nil { | ||
84 | return nil, hcl.Diagnostics{ | ||
85 | { | ||
86 | Severity: hcl.DiagError, | ||
87 | Summary: "Failed to read file", | ||
88 | Detail: fmt.Sprintf("The file %q was opened, but an error occured while reading it.", filename), | ||
89 | }, | ||
90 | } | ||
91 | } | ||
92 | |||
93 | return Parse(src, filename) | ||
94 | } | ||