hcl_edit/expr/
func_call.rs

1use crate::expr::{Expression, IntoIter, Iter, IterMut};
2use crate::{Decor, Decorate, Decorated, Ident, RawString};
3use std::ops::Range;
4
5/// Type representing a (potentially namespaced) function name.
6#[derive(Debug, Clone, PartialEq, Eq)]
7pub struct FuncName {
8    /// The function's namespace components, if any.
9    pub namespace: Vec<Decorated<Ident>>,
10    /// The function name.
11    pub name: Decorated<Ident>,
12}
13
14impl FuncName {
15    /// Create a new `FuncName` from a name identifier.
16    pub fn new(name: impl Into<Decorated<Ident>>) -> FuncName {
17        FuncName {
18            namespace: Vec::new(),
19            name: name.into(),
20        }
21    }
22
23    /// Sets the function namespace from an iterator of namespace parts.
24    pub fn set_namespace<I>(&mut self, namespace: I)
25    where
26        I: IntoIterator,
27        I::Item: Into<Decorated<Ident>>,
28    {
29        self.namespace = namespace.into_iter().map(Into::into).collect();
30    }
31
32    /// Returns `true` if the function name is namespaced.
33    pub fn is_namespaced(&self) -> bool {
34        !self.namespace.is_empty()
35    }
36
37    pub(crate) fn despan(&mut self, input: &str) {
38        for scope in &mut self.namespace {
39            scope.decor_mut().despan(input);
40        }
41        self.name.decor_mut().despan(input);
42    }
43}
44
45impl<T> From<T> for FuncName
46where
47    T: Into<Decorated<Ident>>,
48{
49    fn from(name: T) -> Self {
50        FuncName {
51            namespace: Vec::new(),
52            name: name.into(),
53        }
54    }
55}
56
57/// Type representing a function call.
58#[derive(Debug, Clone, Eq)]
59pub struct FuncCall {
60    /// The function name.
61    pub name: FuncName,
62    /// The arguments between the function call's `(` and `)` argument delimiters.
63    pub args: FuncArgs,
64
65    decor: Decor,
66    span: Option<Range<usize>>,
67}
68
69impl FuncCall {
70    /// Create a new `FuncCall` from an identifier and arguments.
71    pub fn new(name: impl Into<FuncName>, args: FuncArgs) -> FuncCall {
72        FuncCall {
73            name: name.into(),
74            args,
75            decor: Decor::default(),
76            span: None,
77        }
78    }
79
80    pub(crate) fn despan(&mut self, input: &str) {
81        self.decor.despan(input);
82        self.name.despan(input);
83        self.args.despan(input);
84    }
85}
86
87impl PartialEq for FuncCall {
88    fn eq(&self, other: &Self) -> bool {
89        self.name == other.name && self.args == other.args
90    }
91}
92
93/// Type representing the arguments of a function call.
94///
95/// In the HCL grammar, function arguments are delimited by `(` and `)`.
96#[derive(Debug, Clone, Eq, Default)]
97pub struct FuncArgs {
98    args: Vec<Expression>,
99    expand_final: bool,
100    trailing: RawString,
101    trailing_comma: bool,
102    decor: Decor,
103    span: Option<Range<usize>>,
104}
105
106impl FuncArgs {
107    /// Constructs new, empty `FuncArgs`.
108    #[inline]
109    pub fn new() -> Self {
110        FuncArgs::default()
111    }
112
113    /// Constructs new, empty `FuncArgs` with at least the specified capacity.
114    #[inline]
115    pub fn with_capacity(capacity: usize) -> Self {
116        FuncArgs {
117            args: Vec::with_capacity(capacity),
118            ..Default::default()
119        }
120    }
121
122    /// Returns `true` if the function arguments are empty.
123    #[inline]
124    pub fn is_empty(&self) -> bool {
125        self.args.is_empty()
126    }
127
128    /// Returns the number of function arguments, also referred to as its 'length'.
129    #[inline]
130    pub fn len(&self) -> usize {
131        self.args.len()
132    }
133
134    /// Clears the function arguments.
135    #[inline]
136    pub fn clear(&mut self) {
137        self.args.clear();
138    }
139
140    /// Returns a reference to the argument at the given index, or `None` if the index is out of
141    /// bounds.
142    #[inline]
143    pub fn get(&self, index: usize) -> Option<&Expression> {
144        self.args.get(index)
145    }
146
147    /// Returns a mutable reference to the argument at the given index, or `None` if the index is
148    /// out of bounds.
149    #[inline]
150    pub fn get_mut(&mut self, index: usize) -> Option<&mut Expression> {
151        self.args.get_mut(index)
152    }
153
154    /// Inserts an argument at position `index`, shifting all arguments after it to the right.
155    ///
156    /// # Panics
157    ///
158    /// Panics if `index > len`.
159    #[inline]
160    pub fn insert(&mut self, index: usize, arg: impl Into<Expression>) {
161        self.args.insert(index, arg.into());
162    }
163
164    /// Removes the last argument and returns it, or [`None`] if it is empty.
165    #[inline]
166    pub fn pop(&mut self) -> Option<Expression> {
167        self.args.pop()
168    }
169
170    /// Appends an argument.
171    ///
172    /// # Panics
173    ///
174    /// Panics if the new capacity exceeds `isize::MAX` bytes.
175    #[inline]
176    pub fn push(&mut self, arg: impl Into<Expression>) {
177        self.args.push(arg.into());
178    }
179
180    /// Removes and returns the argument at position `index`, shifting all arguments after it to
181    /// the left.
182    ///
183    /// Like `Vec::remove`, the argument is removed by shifting all of the arguments that follow
184    /// it, preserving their relative order. **This perturbs the index of all of those elements!**
185    ///
186    /// # Panics
187    ///
188    /// Panics if `index` is out of bounds.
189    #[inline]
190    pub fn remove(&mut self, index: usize) -> Expression {
191        self.args.remove(index)
192    }
193
194    /// An iterator visiting all values in insertion order. The iterator element type is `&'a
195    /// Expression`.
196    #[inline]
197    pub fn iter(&self) -> Iter<'_> {
198        Box::new(self.args.iter())
199    }
200
201    /// An iterator visiting all values in insertion order, with mutable references to the values.
202    /// The iterator element type is `&'a mut Expression`.
203    #[inline]
204    pub fn iter_mut(&mut self) -> IterMut<'_> {
205        Box::new(self.args.iter_mut())
206    }
207
208    /// Returns `true` if the final argument is a `...` list expansion.
209    #[inline]
210    pub fn expand_final(&self) -> bool {
211        self.expand_final
212    }
213
214    /// Set whether the final argument should be a `...` list expansion.
215    #[inline]
216    pub fn set_expand_final(&mut self, yes: bool) {
217        self.expand_final = yes;
218    }
219
220    /// Return a reference to raw trailing decor before the function argument's closing `)`.
221    #[inline]
222    pub fn trailing(&self) -> &RawString {
223        &self.trailing
224    }
225
226    /// Set the raw trailing decor before the function argument's closing `)`.
227    #[inline]
228    pub fn set_trailing(&mut self, trailing: impl Into<RawString>) {
229        self.trailing = trailing.into();
230    }
231
232    /// Returns `true` if the function arguments use a trailing comma.
233    #[inline]
234    pub fn trailing_comma(&self) -> bool {
235        self.trailing_comma
236    }
237
238    /// Set whether the function arguments will use a trailing comma.
239    #[inline]
240    pub fn set_trailing_comma(&mut self, yes: bool) {
241        self.trailing_comma = yes;
242    }
243
244    pub(crate) fn despan(&mut self, input: &str) {
245        self.decor.despan(input);
246        for arg in &mut self.args {
247            arg.despan(input);
248        }
249
250        self.trailing.despan(input);
251    }
252}
253
254impl PartialEq for FuncArgs {
255    fn eq(&self, other: &Self) -> bool {
256        self.args == other.args
257            && self.trailing_comma == other.trailing_comma
258            && self.trailing == other.trailing
259    }
260}
261
262impl From<Vec<Expression>> for FuncArgs {
263    fn from(args: Vec<Expression>) -> Self {
264        FuncArgs {
265            args,
266            ..Default::default()
267        }
268    }
269}
270
271impl<T> Extend<T> for FuncArgs
272where
273    T: Into<Expression>,
274{
275    fn extend<I>(&mut self, iterable: I)
276    where
277        I: IntoIterator<Item = T>,
278    {
279        let iter = iterable.into_iter();
280        let reserve = if self.is_empty() {
281            iter.size_hint().0
282        } else {
283            (iter.size_hint().0 + 1) / 2
284        };
285        self.args.reserve(reserve);
286        iter.for_each(|v| self.push(v));
287    }
288}
289
290impl<T> FromIterator<T> for FuncArgs
291where
292    T: Into<Expression>,
293{
294    fn from_iter<I>(iterable: I) -> Self
295    where
296        I: IntoIterator<Item = T>,
297    {
298        let iter = iterable.into_iter();
299        let lower = iter.size_hint().0;
300        let mut func_args = FuncArgs::with_capacity(lower);
301        func_args.extend(iter);
302        func_args
303    }
304}
305
306impl IntoIterator for FuncArgs {
307    type Item = Expression;
308    type IntoIter = IntoIter;
309
310    fn into_iter(self) -> Self::IntoIter {
311        Box::new(self.args.into_iter())
312    }
313}
314
315impl<'a> IntoIterator for &'a FuncArgs {
316    type Item = &'a Expression;
317    type IntoIter = Iter<'a>;
318
319    fn into_iter(self) -> Self::IntoIter {
320        self.iter()
321    }
322}
323
324impl<'a> IntoIterator for &'a mut FuncArgs {
325    type Item = &'a mut Expression;
326    type IntoIter = IterMut<'a>;
327
328    fn into_iter(self) -> Self::IntoIter {
329        self.iter_mut()
330    }
331}
332
333decorate_impl!(FuncCall, FuncArgs);
334span_impl!(FuncCall, FuncArgs);