#hcl #serde #serialization

hcl-rs

HCL parser and formatter for rust with serde support

39 releases (11 breaking)

Uses new Rust 2021

new 0.12.3 Jan 24, 2023
0.11.2 Dec 31, 2022
0.10.0 Nov 17, 2022
0.6.4 Jul 30, 2022
0.3.3 Mar 26, 2022

#64 in Encoding

Download history 310/week @ 2022-10-07 226/week @ 2022-10-14 170/week @ 2022-10-21 177/week @ 2022-10-28 159/week @ 2022-11-04 98/week @ 2022-11-11 224/week @ 2022-11-18 132/week @ 2022-11-25 135/week @ 2022-12-02 156/week @ 2022-12-09 50/week @ 2022-12-16 133/week @ 2022-12-23 205/week @ 2022-12-30 122/week @ 2023-01-06 170/week @ 2023-01-13 392/week @ 2023-01-20

921 downloads per month
Used in 9 crates (7 directly)

MIT license

490KB
11K SLoC

hcl-rs

Build Status crates.io docs.rs MIT License

A rust library for interacting with the Hashicorp Configuration Language (HCL).

Features

  • A parser for the HCL syntax specification
  • Types for all HCL structures, e.g. body, blocks and attributes
  • Supporting macros like body! for constructing HCL data structures
  • Supports the expression and template 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

Deserialization examples

Deserialize arbitrary HCL according to the HCL JSON Specification:

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:

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:

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 to learn how you can construct HCL blocks when serializing custom types.

Expression evaluation

The eval module documentation contains more details and examples for expression and template evaluation, but here's a very short example:

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 for usage examples.

Contributing

Contributions are welcome! Please read CONTRIBUTING.md before creating a PR.

License

The source code of hcl-rs is released under the MIT License. See the bundled LICENSE file for details.

Dependencies

~2.3–3MB
~63K SLoC