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
    }
}