Skip to content

Commit

Permalink
feat: add Expression::VariableExpr (#62)
Browse files Browse the repository at this point in the history
This adds supports for parsing and serializing variable expressions. Right now only bare identifiers like `var` are supported. Element access like `var.foo` will come later since this is a different type of expression.
  • Loading branch information
martinohmann committed Sep 7, 2022
1 parent 12e88a3 commit 2b6e81f
Show file tree
Hide file tree
Showing 8 changed files with 34 additions and 11 deletions.
1 change: 1 addition & 0 deletions src/format/impls.rs
Expand Up @@ -105,6 +105,7 @@ impl Format for Expression {
Expression::Object(object) => format_object(fmt, object),
Expression::Raw(raw) => raw.format(fmt),
Expression::TemplateExpr(expr) => expr.format(fmt),
Expression::VariableExpr(ident) => ident.format(fmt),
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/parser/mod.rs
Expand Up @@ -176,7 +176,8 @@ fn parse_expr_term(pair: Pair<Rule>) -> Result<Expression> {
}
Rule::Tuple => parse_expressions(pair).map(Expression::Array),
Rule::Object => parse_object(pair).map(Expression::Object),
// @TODO(mohmann): Process ForExpr, VariableExpr etc.
Rule::VariableExpr => Ok(Expression::VariableExpr(parse_ident(pair).into())),
// @TODO(mohmann): Process ForExpr, etc.
_ => Ok(Expression::Raw(raw_expression(pair.as_str()))),
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/parser/tests.rs
Expand Up @@ -670,12 +670,12 @@ fn template_expr() {

let expected_template = Template::new()
.add_literal("bar ")
.add_interpolation(Expression::Raw("baz".into()))
.add_interpolation(Expression::VariableExpr(Identifier::new("baz")))
.add_literal(" ")
.add_directive(
IfDirective::new(
IfExpr::new(
Expression::Raw("cond".into()),
Expression::VariableExpr(Identifier::new("cond")),
Template::new().add_literal("qux"),
)
.with_strip_mode(StripMode::Start),
Expand Down
4 changes: 4 additions & 0 deletions src/ser/tests.rs
Expand Up @@ -333,6 +333,10 @@ fn roundtrip() {
"${var.team}".into(),
))),
),
(
ObjectKey::Identifier("environment".into()),
Expression::VariableExpr("environment".into()),
),
]),
))
.build(),
Expand Down
2 changes: 2 additions & 0 deletions src/structure/de.rs
Expand Up @@ -260,6 +260,7 @@ impl<'de> de::Deserializer<'de> for Expression {
Expression::Object(object) => visitor.visit_map(object.into_deserializer()),
Expression::Raw(expr) => expr.into_deserializer().deserialize_any(visitor),
Expression::TemplateExpr(expr) => expr.into_deserializer().deserialize_any(visitor),
Expression::VariableExpr(expr) => expr.into_deserializer().deserialize_any(visitor),
}
}

Expand Down Expand Up @@ -287,6 +288,7 @@ impl VariantName for Expression {
Expression::Object(_) => "Object",
Expression::Raw(_) => "Raw",
Expression::TemplateExpr(_) => "TemplateExpr",
Expression::VariableExpr(_) => "VariableExpr",
}
}
}
Expand Down
9 changes: 9 additions & 0 deletions src/structure/expression.rs
Expand Up @@ -30,6 +30,8 @@ pub enum Expression {
Object(Object<ObjectKey, Expression>),
/// A quoted string or heredoc that embeds a program written in the template sub-language.
TemplateExpr(Box<TemplateExpr>),
/// Represents a variable name identifier.
VariableExpr(Identifier),
/// Represents a raw HCL expression. This includes any expression kind that does match any of
/// the enum variants above. See [`RawExpression`] for more details.
Raw(RawExpression),
Expand All @@ -45,6 +47,7 @@ impl From<Expression> for Value {
Expression::Array(array) => array.into_iter().collect(),
Expression::Object(object) => object.into_iter().collect(),
Expression::TemplateExpr(expr) => Value::String(expr.to_string()),
Expression::VariableExpr(ident) => Value::String(RawExpression(ident.0).into()),
Expression::Raw(raw) => Value::String(raw.into()),
}
}
Expand Down Expand Up @@ -166,6 +169,12 @@ impl From<TemplateExpr> for Expression {
}
}

impl From<Identifier> for Expression {
fn from(ident: Identifier) -> Self {
Expression::VariableExpr(ident)
}
}

/// Represents an object key.
#[derive(Deserialize, Serialize, Debug, Clone, PartialEq, Eq, Hash)]
#[serde(rename = "$hcl::object_key")]
Expand Down
8 changes: 7 additions & 1 deletion src/structure/ser/expression.rs
@@ -1,5 +1,7 @@
use super::{template::TemplateExprSerializer, StringSerializer};
use crate::{serialize_unsupported, Error, Expression, Object, ObjectKey, RawExpression, Result};
use crate::{
serialize_unsupported, Error, Expression, Identifier, Object, ObjectKey, RawExpression, Result,
};
use serde::ser::{self, Impossible};
use std::fmt::Display;

Expand Down Expand Up @@ -105,6 +107,10 @@ impl ser::Serializer for ExpressionSerializer {
Ok(Expression::Raw(RawExpression::from(
value.serialize(StringSerializer)?,
)))
} else if name == "$hcl::identifier" {
Ok(Expression::VariableExpr(Identifier::from(
value.serialize(StringSerializer)?,
)))
} else {
value.serialize(self)
}
Expand Down
14 changes: 7 additions & 7 deletions src/template.rs
Expand Up @@ -20,15 +20,15 @@
//! # use std::error::Error;
//! #
//! # fn main() -> Result<(), Box<dyn Error>> {
//! use hcl::{template::{Interpolation, Template}};
//! use hcl::{RawExpression, TemplateExpr};
//! use hcl::template::Template;
//! use hcl::{Expression, Identifier, TemplateExpr};
//!
//! let expr = TemplateExpr::QuotedString(String::from("Hello ${name}!"));
//! let template = Template::from_expr(&expr)?;
//!
//! let expected = Template::new()
//! .add_literal("Hello ")
//! .add_interpolation(Interpolation::new(RawExpression::new("name")))
//! .add_interpolation(Expression::VariableExpr(Identifier::new("name")))
//! .add_literal("!");
//!
//! assert_eq!(expected, template);
Expand All @@ -43,8 +43,8 @@
//! # use std::error::Error;
//! #
//! # fn main() -> Result<(), Box<dyn Error>> {
//! use hcl::{template::{ForDirective, ForExpr, Interpolation, StripMode, Template}};
//! use hcl::{Identifier, RawExpression};
//! use hcl::{template::{ForDirective, ForExpr, StripMode, Template}};
//! use hcl::{Expression, Identifier};
//! use std::str::FromStr;
//!
//! let raw = r#"
Expand All @@ -62,11 +62,11 @@
//! ForDirective::new(
//! ForExpr::new(
//! Identifier::new("item"),
//! RawExpression::new("items"),
//! Expression::VariableExpr(Identifier::new("items")),
//! Template::new()
//! .add_literal("- ")
//! .add_interpolation(
//! Interpolation::new(RawExpression::new("item"))
//! Expression::VariableExpr(Identifier::new("item"))
//! )
//! .add_literal("\n")
//! )
Expand Down

0 comments on commit 2b6e81f

Please sign in to comment.