pdk-script 1.9.0-alpha.1

PDK Script
Documentation
// Copyright (c) 2026, Salesforce, Inc.,
// All rights reserved.
// For full license text, see the LICENSE.txt file

use std::fmt::{Display, Formatter};

use serde::de::Visitor;
use serde::{Deserialize, Deserializer};

use pel::expression::Expression as PelExpression;
use pel::parser::{Parser, ParsingUnitError};

/// An evaluable expression.
#[derive(PartialEq, Clone, Debug)]
pub struct Expression {
    pub(crate) source: Option<String>,
    pub(crate) expression: PelExpression,
}

impl Expression {
    fn new(expression: PelExpression) -> Self {
        Self {
            source: None,
            expression,
        }
    }

    pub(crate) fn with_source(mut self, source: Option<String>) -> Self {
        self.source = source;
        self
    }
}

impl Display for Expression {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        let source = self.source.as_deref().unwrap_or_default();
        f.write_fmt(format_args!("#[{source}]"))
    }
}

impl<'de> Deserialize<'de> for Expression {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        struct ResolverVisitor;

        impl Visitor<'_> for ResolverVisitor {
            type Value = Expression;

            fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
                formatter.write_str("PEL Expression")
            }

            fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
            where
                E: serde::de::Error,
            {
                let effective_value = if value.is_empty() {
                    r##"P[[":null", "0-4"], "#[null]"]"##
                } else {
                    value
                };

                let (expression, source) =
                    Parser::new()
                        .parse_unit(effective_value)
                        .map_err(|error| match error {
                            ParsingUnitError::InvalidContainer => serde::de::Error::invalid_type(
                                serde::de::Unexpected::Str(value),
                                &self,
                            ),
                            _ => serde::de::Error::custom(format_args!(
                                "Unexpected error when parsing expression '{value}': {error}"
                            )),
                        })?;

                Ok(Expression::new(expression).with_source(source))
            }
        }

        deserializer.deserialize_str(ResolverVisitor)
    }
}