1use crate::compiler::prelude::*;
2
3fn keys(value: Value) -> Resolved {
4 let object = value.try_object()?;
5 let keys = object.into_keys().map(Value::from);
6 Ok(Value::Array(keys.collect()))
7}
8
9#[derive(Debug)]
10pub struct Keys;
11
12impl Function for Keys {
13 fn identifier(&self) -> &'static str {
14 "keys"
15 }
16
17 fn usage(&self) -> &'static str {
18 "Returns the keys from the object passed into the function."
19 }
20
21 fn category(&self) -> &'static str {
22 Category::Enumerate.as_ref()
23 }
24
25 fn return_kind(&self) -> u16 {
26 kind::ARRAY
27 }
28
29 fn return_rules(&self) -> &'static [&'static str] {
30 &["Returns an array of all the keys"]
31 }
32
33 fn parameters(&self) -> &'static [Parameter] {
34 const PARAMETERS: &[Parameter] = &[Parameter::required(
35 "value",
36 kind::OBJECT,
37 "The object to extract keys from.",
38 )];
39 PARAMETERS
40 }
41
42 fn examples(&self) -> &'static [Example] {
43 &[example! {
44 title: "Get keys from the object",
45 source: indoc! {r#"
46 keys({
47 "key1": "val1",
48 "key2": "val2"
49 })
50 "#},
51 result: Ok(r#"["key1", "key2"]"#),
52 }]
53 }
54
55 fn compile(
56 &self,
57 _state: &TypeState,
58 _ctx: &mut FunctionCompileContext,
59 arguments: ArgumentList,
60 ) -> Compiled {
61 let value = arguments.required("value");
62 Ok(KeysFn { value }.as_expr())
63 }
64}
65
66#[derive(Debug, Clone)]
67struct KeysFn {
68 value: Box<dyn Expression>,
69}
70
71impl FunctionExpression for KeysFn {
72 fn resolve(&self, ctx: &mut Context) -> Resolved {
73 keys(self.value.resolve(ctx)?)
74 }
75
76 fn type_def(&self, _state: &state::TypeState) -> TypeDef {
77 TypeDef::array(Collection::empty().with_unknown(Kind::bytes())).infallible()
78 }
79}