hcl/expr/func_call.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
use super::Expression;
use crate::format;
use crate::Identifier;
use serde::Deserialize;
use std::fmt;
/// Type representing a (potentially namespaced) function name.
#[derive(Deserialize, Debug, Clone, PartialEq, Eq)]
pub struct FuncName {
/// The function's namespace components, if any.
pub namespace: Vec<Identifier>,
/// The function name.
pub name: Identifier,
}
impl FuncName {
/// Create a new `FuncName` from a name identifier.
pub fn new(name: impl Into<Identifier>) -> FuncName {
FuncName {
namespace: Vec::new(),
name: name.into(),
}
}
/// Adds a namespace to the function name.
pub fn with_namespace<I>(mut self, namespace: I) -> FuncName
where
I: IntoIterator,
I::Item: Into<Identifier>,
{
self.namespace = namespace.into_iter().map(Into::into).collect();
self
}
/// Returns `true` if the function name is namespaced.
pub fn is_namespaced(&self) -> bool {
!self.namespace.is_empty()
}
}
impl<T> From<T> for FuncName
where
T: Into<Identifier>,
{
fn from(name: T) -> Self {
FuncName {
namespace: Vec::new(),
name: name.into(),
}
}
}
impl fmt::Display for FuncName {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// Formatting a `FuncName` as string cannot fail.
let formatted = format::to_string(self).expect("a FuncName failed to format unexpectedly");
f.write_str(&formatted)
}
}
/// Represents a function call expression with zero or more arguments.
#[derive(Deserialize, Debug, Clone, PartialEq, Eq)]
pub struct FuncCall {
/// The function name.
pub name: FuncName,
/// The function arguments.
pub args: Vec<Expression>,
/// If `true`, the final argument should be an array which will expand to be one argument per
/// element.
pub expand_final: bool,
}
impl FuncCall {
/// Creates a new `FuncCall` for the function with given name.
pub fn new<T>(name: T) -> FuncCall
where
T: Into<FuncName>,
{
FuncCall {
name: name.into(),
args: Vec::new(),
expand_final: false,
}
}
/// Creates a new `FuncCallBuilder` for the function with given name.
pub fn builder<T>(name: T) -> FuncCallBuilder
where
T: Into<FuncName>,
{
FuncCallBuilder {
f: FuncCall::new(name),
}
}
}
/// A builder for function calls.
#[derive(Debug)]
pub struct FuncCallBuilder {
f: FuncCall,
}
impl FuncCallBuilder {
/// Adds an argument to the function call.
pub fn arg<T>(mut self, arg: T) -> FuncCallBuilder
where
T: Into<Expression>,
{
self.f.args.push(arg.into());
self
}
/// If `true`, the final argument should be an array which will expand to be one argument per
/// element.
pub fn expand_final(mut self, yes: bool) -> FuncCallBuilder {
self.f.expand_final = yes;
self
}
/// Consumes the `FuncCallBuilder` and returns the `FuncCall`.
pub fn build(self) -> FuncCall {
self.f
}
}