# hcl-rs
[![Build Status](https://github.com/martinohmann/hcl-rs/workflows/ci/badge.svg)](https://github.com/martinohmann/hcl-rs/actions?query=workflow%3Aci)
[![crates.io](https://img.shields.io/crates/v/hcl-rs)](https://crates.io/crates/hcl-rs)
[![docs.rs](https://img.shields.io/docsrs/hcl-rs)](https://docs.rs/hcl-rs)
[![License: Apache 2.0](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
A rust library for interacting with the Hashicorp Configuration Language (HCL).
## Features
- A parser for the [HCL syntax
specification](https://github.com/hashicorp/hcl/blob/main/hclsyntax/spec.md)
- Types for all HCL structures, e.g. body, blocks and attributes
- Supporting macros like `body!` for constructing HCL data structures
- Supports the
[expression](https://github.com/hashicorp/hcl/blob/main/hclsyntax/spec.md#expressions)
and
[template](https://github.com/hashicorp/hcl/blob/main/hclsyntax/spec.md#templates)
sub-languages in attribute values
- Support for deserializing and serializing arbitrary types that
implement `serde::Deserialize` or `serde::Serialize`
- Evaluation of the HCL expression and template sub-languages
## Cargo features
- `perf`: enables parser performance optimizations such as inlining of small
strings on the stack. This feature is disabled by default.
## Deserialization examples
Deserialize arbitrary HCL according to the [HCL JSON
Specification](https://github.com/hashicorp/hcl/blob/main/json/spec.md):
```rust
use serde_json::{json, Value};
let input = r#"
some_attr = {
foo = [1, 2]
bar = true
}
some_block "some_block_label" {
attr = "value"
}
"#;
let expected = json!({
"some_attr": {
"foo": [1, 2],
"bar": true
},
"some_block": {
"some_block_label": {
"attr": "value"
}
}
});
let value: Value = hcl::from_str(input).unwrap();
assert_eq!(value, expected);
```
If you need to preserve context about the HCL structure, deserialize into
`hcl::Body` instead:
```rust
use hcl::{Block, Body, Expression};
let input = r#"
some_attr = {
"foo" = [1, 2]
"bar" = true
}
some_block "some_block_label" {
attr = "value"
}
"#;
let expected = Body::builder()
.add_attribute((
"some_attr",
Expression::from_iter([
("foo", Expression::from(vec![1, 2])),
("bar", Expression::Bool(true)),
]),
))
.add_block(
Block::builder("some_block")
.add_label("some_block_label")
.add_attribute(("attr", "value"))
.build(),
)
.build();
let body: Body = hcl::from_str(input).unwrap();
assert_eq!(body, expected);
```
## Serialization examples
An example to serialize some terraform configuration:
```rust
use hcl::expr::Traversal;
use hcl::{Block, Body, Variable};
let body = Body::builder()
.add_block(
Block::builder("resource")
.add_label("aws_sns_topic_subscription")
.add_label("my-subscription")
.add_attribute((
"topic_arn",
Traversal::builder(Variable::new("aws_sns_topic").unwrap())
.attr("my-topic")
.attr("arn")
.build(),
))
.add_attribute(("protocol", "sqs"))
.add_attribute((
"endpoint",
Traversal::builder(Variable::new("aws_sqs_queue").unwrap())
.attr("my-queue")
.attr("arn")
.build(),
))
.build(),
)
.build();
let expected = r#"
resource "aws_sns_topic_subscription" "my-subscription" {
topic_arn = aws_sns_topic.my-topic.arn
protocol = "sqs"
endpoint = aws_sqs_queue.my-queue.arn
}
"#.trim_start();
let serialized = hcl::to_string(&body).unwrap();
assert_eq!(serialized, expected);
```
Also have a look at the other examples provided in the [documentation of the
`ser` module](https://docs.rs/hcl-rs/latest/hcl/ser/index.html) to learn how you can construct HCL blocks when serializing custom types.
## Expression evaluation
The [`eval` module
documentation](https://docs.rs/hcl-rs/latest/hcl/eval/index.html) contains more
details and examples for expression and template evaluation, but here's a very
short example:
```rust
use hcl::Value;
use hcl::eval::{Context, Evaluate};
use hcl::expr::TemplateExpr;
let expr = TemplateExpr::from("Hello ${name}!");
let mut ctx = Context::new();
ctx.declare_var("name", "World");
assert_eq!(expr.evaluate(&ctx).unwrap(), Value::from("Hello World!"));
```
## Macros
This crate provides a couple of macros to ease building HCL data structures.
Have a look at [their
documentation](https://docs.rs/hcl-rs/latest/hcl/macro.body.html) for usage
examples.
## Contributing
Contributions are welcome! Please read
[`CONTRIBUTING.md`](https://github.com/martinohmann/hcl-rs/blob/main/CONTRIBUTING.md)
before creating a PR.
## License
The source code of hcl-rs is licensed under either of [Apache License, Version
2.0](https://github.com/martinohmann/hcl-rs/blob/main/LICENSE-APACHE) or [MIT
license](https://github.com/martinohmann/hcl-rs/blob/main/LICENSE-MIT) at your
option.