1use crate::compiler::prelude::{TypeDef as VrlTypeDef, *};
2
3fn type_def(type_def: &VrlTypeDef) -> Value {
4 let mut tree = type_def.kind().canonicalize().debug_info();
5
6 if type_def.is_fallible() {
7 tree.insert("fallible".to_owned().into(), true.into());
8 }
9
10 tree.into()
11}
12
13#[derive(Clone, Copy, Debug)]
18pub struct TypeDef;
19
20impl Function for TypeDef {
21 fn identifier(&self) -> &'static str {
22 "type_def"
23 }
24
25 fn usage(&self) -> &'static str {
26 indoc! {"
27 Returns the type definition of an expression at runtime.
28
29 This is a debug function that is *UNSTABLE*. Behavior is *NOT* guaranteed even though it is technically usable.
30 "}
31 }
32
33 fn category(&self) -> &'static str {
34 Category::Type.as_ref()
35 }
36
37 fn return_kind(&self) -> u16 {
38 kind::ANY
39 }
40
41 fn parameters(&self) -> &'static [Parameter] {
42 const PARAMETERS: &[Parameter] = &[Parameter::required(
43 "value",
44 kind::ANY,
45 "The expression to get the type definition for.",
46 )];
47 PARAMETERS
48 }
49
50 fn examples(&self) -> &'static [Example] {
51 &[example! {
52 title: "return type definition",
53 source: "type_def(42)",
54 result: Ok(r#"{ "integer": true }"#),
55 }]
56 }
57
58 fn compile(
59 &self,
60 state: &TypeState,
61 _ctx: &mut FunctionCompileContext,
62 arguments: ArgumentList,
63 ) -> Compiled {
64 let value = arguments.required("value");
65 let type_def = value.type_def(state);
66 Ok(TypeDefFn { type_def }.as_expr())
67 }
68}
69
70#[derive(Debug, Clone)]
71struct TypeDefFn {
72 type_def: VrlTypeDef,
73}
74
75impl FunctionExpression for TypeDefFn {
76 fn resolve(&self, _ctx: &mut Context) -> Resolved {
77 Ok(type_def(&self.type_def.clone()))
78 }
79
80 fn type_def(&self, _state: &state::TypeState) -> VrlTypeDef {
81 VrlTypeDef::any()
82 }
83}