Skip to main content

pdk_script/
script.rs

1// Copyright 2023 Salesforce, Inc. All rights reserved.
2use crate::context::input::InputContext;
3use crate::evaluator::Evaluator;
4use crate::expression::Expression;
5use crate::input::Input;
6use pel::expression::Expression as PelExpression;
7use pel::runtime::value::Value as PelValue;
8use pel::runtime::{Evaluation, Runtime, RuntimeError};
9use thiserror::Error;
10
11/// A builder for [`ScriptParser`]s.
12pub struct ScriptingEngine {}
13
14impl ScriptingEngine {
15    /// Creates a new [`ScriptParser`].
16    pub fn script(expression: &Expression) -> ScriptParser {
17        ScriptParser::new(expression)
18    }
19}
20
21/// Parser for script [`Expression`]s.
22pub struct ScriptParser<'a> {
23    expression: &'a Expression,
24    input_context: InputContext,
25}
26
27impl<'a> ScriptParser<'a> {
28    pub(crate) fn new(expression: &'a Expression) -> Self {
29        Self {
30            expression,
31            input_context: InputContext::default(),
32        }
33    }
34
35    /// Sets an `input`.
36    pub fn input(mut self, input: Input) -> Self {
37        match input {
38            Input::Payload(fmt) => self.input_context.set_payload_input(fmt),
39            Input::Vars(vars) => {
40                self.input_context.push_var_input(vars);
41            }
42            Input::Attributes => {
43                self.input_context.set_attributes_input();
44            }
45            Input::Authentication => self.input_context.set_authentication_input(),
46        }
47        self
48    }
49
50    /// Compiles the inputs and returns a new [`Script`].
51    pub fn compile(self) -> Result<Script, ScriptError> {
52        let result = Runtime::new()
53            .eval_with_context(&self.expression.expression, &self.input_context)
54            .map_err(ScriptError::Error)?;
55
56        match result {
57            Evaluation::Complete(_, v) => Ok(Script::new(None, Some(v), self.input_context)),
58            Evaluation::Partial(e) => Ok(Script::new(Some(e), None, self.input_context)),
59        }
60    }
61}
62
63/// Represents the [`ScriptParser::compile`] error.
64#[derive(Error, Debug)]
65pub enum ScriptError {
66    /// Represents a compiler error.
67    #[error("Error compiling expression: {0}")]
68    Error(RuntimeError),
69}
70
71/// An script relating an [`Expression`] with their [`Input`]s.
72#[derive(Debug, Clone)]
73pub struct Script {
74    evaluation: Option<PelExpression>,
75    result: Option<PelValue>,
76    context: InputContext,
77}
78
79impl Script {
80    pub(crate) fn new(
81        evaluation: Option<PelExpression>,
82        result: Option<PelValue>,
83        context: InputContext,
84    ) -> Self {
85        Self {
86            evaluation,
87            result,
88            context,
89        }
90    }
91
92    /// Creates an [`Evaluator`] for the script.
93    pub fn evaluator(&self) -> Evaluator {
94        Evaluator::new(self.evaluation.clone(), self.result.clone(), &self.context)
95    }
96}