vrl/stdlib/
pop.rs

1use crate::compiler::prelude::*;
2
3fn pop(value: Value) -> Resolved {
4    let mut value = value.try_array()?;
5    value.pop();
6    Ok(value.into())
7}
8
9#[derive(Clone, Copy, Debug)]
10pub struct Pop;
11
12impl Function for Pop {
13    fn identifier(&self) -> &'static str {
14        "pop"
15    }
16
17    fn usage(&self) -> &'static str {
18        "Removes the last item from the `value` array."
19    }
20
21    fn category(&self) -> &'static str {
22        Category::Array.as_ref()
23    }
24
25    fn return_kind(&self) -> u16 {
26        kind::ARRAY
27    }
28
29    fn return_rules(&self) -> &'static [&'static str] {
30        &["The original `value` is not modified."]
31    }
32
33    fn parameters(&self) -> &'static [Parameter] {
34        const PARAMETERS: &[Parameter] = &[Parameter::required(
35            "value",
36            kind::ARRAY,
37            "The target array.",
38        )];
39        PARAMETERS
40    }
41
42    fn examples(&self) -> &'static [Example] {
43        &[example! {
44            title: "Pop an item from an array",
45            source: "pop([1, 2, 3])",
46            result: Ok("[1, 2]"),
47        }]
48    }
49
50    fn compile(
51        &self,
52        _state: &state::TypeState,
53        _ctx: &mut FunctionCompileContext,
54        arguments: ArgumentList,
55    ) -> Compiled {
56        let value = arguments.required("value");
57
58        Ok(PopFn { value }.as_expr())
59    }
60}
61
62#[derive(Debug, Clone)]
63struct PopFn {
64    value: Box<dyn Expression>,
65}
66
67impl FunctionExpression for PopFn {
68    fn resolve(&self, ctx: &mut Context) -> Resolved {
69        let value = self.value.resolve(ctx)?;
70
71        pop(value)
72    }
73
74    fn type_def(&self, state: &state::TypeState) -> TypeDef {
75        self.value
76            .type_def(state)
77            .fallible_unless(Kind::array(Collection::any()))
78            .restrict_array()
79    }
80}
81
82#[cfg(test)]
83mod tests {
84    use super::*;
85    use crate::{btreemap, value};
86
87    test_function![
88        pop => Pop;
89
90        empty_array {
91            args: func_args![value: value!([])],
92            want: Ok(value!([])),
93            tdef: TypeDef::array(Collection::empty()),
94        }
95
96        null_array {
97            args: func_args![value: value!(null)],
98            want: Err("expected array, got null"),
99            tdef: TypeDef::array(Collection::any()).fallible(),
100        }
101
102        mixed_array_types {
103            args: func_args![value: value!([1, 2, 3, true, 5.0, "bar"])],
104            want: Ok(value!([1, 2, 3, true, 5.0])),
105            tdef: TypeDef::array(btreemap! {
106                Index::from(0) => Kind::integer(),
107                Index::from(1) => Kind::integer(),
108                Index::from(2) => Kind::integer(),
109                Index::from(3) => Kind::boolean(),
110                Index::from(4) => Kind::float(),
111                Index::from(5) => Kind::bytes(),
112            }),
113        }
114
115        integer_array {
116            args: func_args![value: value!([0, 1, 2, 3])],
117            want: Ok(value!([0, 1, 2])),
118            tdef: TypeDef::array(btreemap! {
119                Index::from(0) => Kind::integer(),
120                Index::from(1) => Kind::integer(),
121                Index::from(2) => Kind::integer(),
122                Index::from(3) => Kind::integer(),
123            }),
124        }
125
126    ];
127}