hcl/expr/
func_call.rs

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