Documentation ¶
Overview ¶
Package hclpack provides a straightforward representation of HCL block/body structure that can be easily serialized and deserialized for compact transmission (e.g. over a network) without transmitting the full source code.
Expressions are retained in native syntax source form so that their evaluation can be delayed until a package structure is decoded by some other system that has enough information to populate the evaluation context.
Packed structures retain source location information but do not retain actual source code. To make sense of source locations returned in diagnostics and via other APIs the caller must somehow gain access to the original source code that the packed representation was built from, which is a problem that must be solved somehow by the calling application.
Example (MarshalJSON) ¶
package main import ( "bytes" "encoding/json" "fmt" "os" "github.com/hashicorp/hcl2/hcl" "github.com/hashicorp/hcl2/hclpack" ) func main() { src := ` service "example" { priority = 2 platform { os = "linux" arch = "amd64" } process "web" { exec = ["./webapp"] } process "worker" { exec = ["./worker"] } } ` body, diags := hclpack.PackNativeFile([]byte(src), "example.svc", hcl.Pos{Line: 1, Column: 1}) if diags.HasErrors() { fmt.Fprintf(os.Stderr, "Failed to parse: %s", diags.Error()) return } jb, err := body.MarshalJSON() if err != nil { fmt.Fprintf(os.Stderr, "Failed to marshal: %s", err) return } // Normally the compact form is best, but we'll indent just for the sake // of this example so the result is readable. var buf bytes.Buffer json.Indent(&buf, jb, "", " ") os.Stdout.Write(buf.Bytes()) }
Output: { "r": { "b": [ { "h": [ "service", "example" ], "b": { "a": { "priority": { "s": "2", "r": "ChAKDA4QDhA" } }, "b": [ { "h": [ "platform" ], "b": { "a": { "arch": { "s": "\"amd64\"", "r": "IiwiJCYsKCo" }, "os": { "s": "\"linux\"", "r": "FiAWGBogHB4" } }, "r": "Li4" }, "r": "EhQSFA" }, { "h": [ "process", "web" ], "b": { "a": { "exec": { "s": "[\"./webapp\"]", "r": "OEA4OjxAPD4" } }, "r": "QkI" }, "r": "MDYwMjQ2" }, { "h": [ "process", "worker" ], "b": { "a": { "exec": { "s": "[\"./worker\"]", "r": "TFRMTlBUUFI" } }, "r": "VlY" }, "r": "REpERkhK" } ], "r": "WFg" }, "r": "AggCBAYI" } ], "r": "Wlo" }, "s": [ "example.svc" ], "p": "BAQEAA4OAAICABISAggMABAQAAYGAAICAggIABAQAgYKAAQEAAoKAAICAAoKAAICAgYGAAgIAAYGAAICAAoKAAICAgoKAggIAA4OAAICAAoKAgwQAAgIAAYGAAICABYWAgoKAggIAA4OAAICABAQAgwQAAgIAAYGAAICABYWAgoKAgYGAgQE" }
Index ¶
- type Attribute
- type Block
- type Body
- func (b *Body) Content(schema *hcl.BodySchema) (*hcl.BodyContent, hcl.Diagnostics)
- func (b *Body) JustAttributes() (hcl.Attributes, hcl.Diagnostics)
- func (b *Body) MarshalJSON() ([]byte, error)
- func (b *Body) MissingItemRange() hcl.Range
- func (b *Body) PartialContent(schema *hcl.BodySchema) (*hcl.BodyContent, hcl.Body, hcl.Diagnostics)
- func (b *Body) UnmarshalJSON(data []byte) error
- type ExprSourceType
- type Expression
- func (e *Expression) Parse() (hcl.Expression, hcl.Diagnostics)
- func (e *Expression) Range() hcl.Range
- func (e *Expression) StartRange() hcl.Range
- func (e *Expression) UnwrapExpression() hcl.Expression
- func (e *Expression) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics)
- func (e *Expression) Variables() []hcl.Traversal
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Attribute ¶
type Attribute struct { Expr Expression Range, NameRange hcl.Range }
Attribute represents an attribute definition within a body.
type Block ¶
type Block struct { Type string Labels []string Body Body DefRange, TypeRange hcl.Range LabelRanges []hcl.Range }
Block represents a nested block within a body.
type Body ¶
type Body struct { Attributes map[string]Attribute ChildBlocks []Block MissingItemRange_ hcl.Range }
Body is an implementation of hcl.Body.
func PackNativeFile ¶
PackNativeFile parses the given source code as HCL native syntax and packs it into a hclpack Body ready to be marshalled.
If the given source code contains syntax errors then error diagnostics will be returned. A non-nil body might still be returned in this case, which allows a cautious caller to still do certain analyses on the result.
func (*Body) Content ¶
func (b *Body) Content(schema *hcl.BodySchema) (*hcl.BodyContent, hcl.Diagnostics)
Content is an implementation of the method of the same name on hcl.Body.
When Content is called directly on a hclpack.Body, all child block bodies are guaranteed to be of type *hclpack.Body, so callers can type-assert to obtain a child Body in order to serialize it separately if needed.
func (*Body) JustAttributes ¶
func (b *Body) JustAttributes() (hcl.Attributes, hcl.Diagnostics)
JustAttributes is an implementation of the method of the same name on hcl.Body.
func (*Body) MarshalJSON ¶
MarshalJSON is an implementation of Marshaler from encoding/json, allowing bodies to be included in other types that are JSON-marshalable.
The result of MarshalJSON is optimized for compactness rather than easy human consumption/editing. Use UnmarshalJSON to decode it.
func (*Body) MissingItemRange ¶
MissingItemRange is an implementation of the method of the same name on hcl.Body.
func (*Body) PartialContent ¶
func (b *Body) PartialContent(schema *hcl.BodySchema) (*hcl.BodyContent, hcl.Body, hcl.Diagnostics)
PartialContent is an implementation of the method of the same name on hcl.Body.
The returned "remain" body may share some backing objects with the receiver, so neither the receiver nor the returned remain body, or any descendent objects within them, may be mutated after this method is used.
When Content is called directly on a hclpack.Body, all child block bodies and the returned "remain" body are guaranteed to be of type *hclpack.Body, so callers can type-assert to obtain a child Body in order to serialize it separately if needed.
func (*Body) UnmarshalJSON ¶
UnmarshalJSON is an implementation of Unmarshaler from encoding/json, allowing bodies to be included in other types that are JSON-unmarshalable.
type ExprSourceType ¶
type ExprSourceType rune
ExprSourceType defines the syntax type used for an expression's source code, which is then used to select a suitable parser for it when evaluating.
const ( // ExprNative indicates that an expression must be parsed as native // expression syntax, with hclsyntax.ParseExpression. ExprNative ExprSourceType = 'N' // ExprTemplate indicates that an expression must be parsed as native // template syntax, with hclsyntax.ParseTemplate. ExprTemplate ExprSourceType = 'T' // ExprLiteralJSON indicates that an expression must be parsed as JSON and // treated literally, using cty/json. This can be used when populating // literal attribute values from a non-HCL source. ExprLiteralJSON ExprSourceType = 'L' )
func (ExprSourceType) String ¶
func (i ExprSourceType) String() string
type Expression ¶
type Expression struct { // Source is the raw source code of the expression, which should be parsed // as the syntax specified by SourceType. Source []byte SourceType ExprSourceType // Range_ and StartRange_ describe the physical extents of the expression // in the original source code. SourceRange_ is its entire range while // StartRange is just the tokens that introduce the expression type. For // simple expression types, SourceRange and StartRange are identical. Range_, StartRange_ hcl.Range }
Expression is an implementation of hcl.Expression in terms of some raw expression source code. The methods of this type will first parse the source code and then pass the call through to the real expression that is produced.
func (*Expression) Parse ¶
func (e *Expression) Parse() (hcl.Expression, hcl.Diagnostics)
Parse attempts to parse the source code of the receiving expression using its indicated source type, returning the expression if possible and any diagnostics produced during parsing.
func (*Expression) Range ¶
func (e *Expression) Range() hcl.Range
func (*Expression) StartRange ¶
func (e *Expression) StartRange() hcl.Range
func (*Expression) UnwrapExpression ¶
func (e *Expression) UnwrapExpression() hcl.Expression
UnwrapExpression parses and returns the underlying expression, if possible.
This is essentially the same as Parse but without the ability to return an error; it is here only to support the static analysis facilities in the main HCL package (ExprList, ExprMap, etc). If any error is encountered during parsing, the result is a static expression that always returns cty.DynamicVal.
This function does not impose any further conversions on the underlying expression, so the result may still not be suitable for the static analysis functions, depending on the source type of the expression and thus what type of physical expression it becomes after decoding.
func (*Expression) Value ¶
func (e *Expression) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics)
Value implements the Value method of hcl.Expression but with the additional step of first parsing the expression source code. This implementation is unusual in that it can potentially return syntax errors, whereas other Value implementations usually work with already-parsed expressions.
func (*Expression) Variables ¶
func (e *Expression) Variables() []hcl.Traversal
Variables implements the Variables method of hcl.Expression but with the additional step of first parsing the expression source code.
Since this method cannot return errors, it will return a nil slice if parsing fails, indicating that no variables are present. This is okay in practice because a subsequent call to Value would fail with syntax errors regardless of what variables are in the context.