martinohmann / hcl-rs

HCL parsing and encoding libraries for rust with serde support
Apache License 2.0
121 stars 14 forks source link

Feature parity with go-hcl #304

Closed srevinsaju closed 5 months ago

srevinsaju commented 11 months ago

Is hcl-rs fully feature compatible with the original HCL implementation?

martinohmann commented 9 months ago

Hi there @srevinsaju!

Sorry for the long wait. hcl-rs (or more specifically hcl-edit) tries to closely follow these specifications:

At the parser level it should support all features that go-hcl does today. However, the implementations for formatting and expression evaluation in hcl-rs are relatively basic at the moment. I'm planning to move formatting and expression evaluation capabilities into hcl-edit (which is used by hcl-rs under the hood and also contains the parser implementation) and would like to make them more powerful.

Another thing that is not included (yet), but might be helpful in the future is the support for HCL schemas in order to validate that a parsed HCL document only contains an allowed set of blocks with expected attributes (e.g. to enable validation that a given terraform configuration only contains well-formed resource and data blocks etc.).

Which HCL features are you interested in specifically? Maybe there's something we can do here.

robmorgan commented 5 months ago

@martinohmann I have a more narrow use case that is a subset of this issue.

Given the following JSON:

{
    "some_attr": {
        "foo": [1, 2],
        "bar": true
    },
    "some_block": {
        "some_block_label": {
            "attr": "value"
        }
    }
}

I'd like to serialize it to the following HCL config:

some_attr = {
      foo = [1, 2]
      bar = true
    }

some_block "some_block_label" {
    attr = "value"
}

Basically I'm trying to create a labeled block element. From what I've read and seen, this would only be possible when using a schema which is currently unsupported. Is there a way to use one of the crates to create this kind of HCL configuration or am I better off using the builder APIs?

Cheers

srevinsaju commented 5 months ago

Sorry for the long wait. hcl-rs (or more specifically hcl-edit) tries to closely follow these specifications:

https://github.com/hashicorp/hcl/blob/main/spec.md
https://github.com/hashicorp/hcl/blob/main/hclsyntax/spec.md
https://github.com/hashicorp/hcl/blob/main/json/spec.md

Looks like that answered my question - thank you! It would be great to drop that in the README.md

martinohmann commented 5 months ago

@robmorgan you can achieve this by using LabeledBlock:

use hcl::ser::LabeledBlock;
use hcl::Value;
use indexmap::IndexMap;

#[derive(serde::Serialize)]
struct Config {
    some_attr: IndexMap<String, Value>,
    some_block: LabeledBlock<IndexMap<String, IndexMap<String, Value>>>,
}

let config = Config {
    some_attr: indexmap! {
        "foo".into() => Value::from(vec![1, 2]),
        "bar".into() => Value::from(true),
    },
    some_block: LabeledBlock::new(indexmap! {
        "some_block_label".into() => indexmap! {
            "attr".into() => Value::from("value"),
        },
    }),
};

println!("{}", hcl::to_string(&config).unwrap());

or via the labeled_block serializer:

use hcl::Value;
use indexmap::IndexMap;

#[derive(serde::Serialize)]
struct Config {
    some_attr: IndexMap<String, Value>,
    #[serde(serialize_with = "hcl::ser::labeled_block")]
    some_block: IndexMap<String, IndexMap<String, Value>>,
}

let config = Config {
    some_attr: indexmap! {
        "foo".into() => Value::from(vec![1, 2]),
        "bar".into() => Value::from(true),
    },
    some_block: indexmap! {
        "some_block_label".into() => indexmap! {
            "attr".into() => Value::from("value"),
        },
    },
};

println!("{}", hcl::to_string(&config).unwrap());

Schema support is something that I'd like to have as well, but it'll be a lot of work to implement this and I simply do not have much spare time for that at the moment.

martinohmann commented 5 months ago

Sorry for the long wait. hcl-rs (or more specifically hcl-edit) tries to closely follow these specifications:

https://github.com/hashicorp/hcl/blob/main/spec.md
https://github.com/hashicorp/hcl/blob/main/hclsyntax/spec.md
https://github.com/hashicorp/hcl/blob/main/json/spec.md

Looks like that answered my question - thank you! It would be great to drop that in the README.md

Thanks for the reminder, I'll try to add this!

robmorgan commented 5 months ago

@martinohmann thanks! I've been playing around with the LabeledBlock example code today, so I guess I was on the right track 👍