hcl-rs 0.18.3

HCL parser and formatter for rust with serde support
Documentation
# 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.