hcl-edit 0.9.6

Parse and modify HCL while preserving comments and whitespace
Documentation
use super::{
    encode_decorated, encode_quoted_string, Encode, EncodeDecorated, EncodeState, BOTH_SPACE_DECOR,
    LEADING_SPACE_DECOR, NO_DECOR, TRAILING_SPACE_DECOR,
};
use crate::structure::{Attribute, Block, BlockLabel, Body, Structure};
use std::fmt::{self, Write};

impl Encode for Body {
    fn encode(&self, buf: &mut EncodeState) -> fmt::Result {
        for (index, structure) in self.iter().enumerate() {
            structure.encode_decorated(buf, NO_DECOR)?;

            if index < self.len() - 1 || !self.prefer_omit_trailing_newline() {
                buf.write_char('\n')?;
            }
        }

        Ok(())
    }
}

impl EncodeDecorated for Structure {
    fn encode_decorated(&self, buf: &mut EncodeState, default_decor: (&str, &str)) -> fmt::Result {
        match self {
            Structure::Attribute(attr) => attr.encode_decorated(buf, default_decor),
            Structure::Block(block) => block.encode_decorated(buf, default_decor),
        }
    }
}

impl Encode for Attribute {
    fn encode(&self, buf: &mut EncodeState) -> fmt::Result {
        self.key.encode_decorated(buf, TRAILING_SPACE_DECOR)?;
        buf.write_char('=')?;
        self.value.encode_decorated(buf, LEADING_SPACE_DECOR)
    }
}

impl Encode for Block {
    fn encode(&self, buf: &mut EncodeState) -> fmt::Result {
        self.ident.encode_decorated(buf, TRAILING_SPACE_DECOR)?;

        for label in &self.labels {
            label.encode_decorated(buf, TRAILING_SPACE_DECOR)?;
        }

        buf.write_char('{')?;

        let body = &self.body;

        encode_decorated(body, buf, NO_DECOR, |buf| {
            if body.prefer_oneline() && (body.is_empty() || body.has_single_attribute()) {
                if let Some(attr) = body.get(0).and_then(Structure::as_attribute) {
                    attr.encode_decorated(buf, BOTH_SPACE_DECOR)?;
                }
            } else {
                buf.write_char('\n')?;

                for structure in body {
                    structure.encode_decorated(buf, NO_DECOR)?;
                    buf.write_char('\n')?;
                }
            }

            Ok(())
        })?;

        buf.write_char('}')
    }
}

impl EncodeDecorated for BlockLabel {
    fn encode_decorated(&self, buf: &mut EncodeState, default_decor: (&str, &str)) -> fmt::Result {
        match self {
            BlockLabel::String(string) => encode_decorated(string, buf, default_decor, |buf| {
                encode_quoted_string(buf, string)
            }),
            BlockLabel::Ident(ident) => ident.encode_decorated(buf, default_decor),
        }
    }
}