pdk-script 1.3.0-alpha.0

PDK Script
Documentation
// Copyright 2023 Salesforce, Inc. All rights reserved.
use crate::bindings::payload::PayloadBinding;
use crate::constants::PAYLOAD;
use crate::context::input::InputContext;
use crate::input::Format;
use crate::value::Value;
use pel::expression::Symbol;
use pel::runtime::value::Value as PelValue;
use pel::runtime::{Binding as PelBinding, Context, ValueHandler};
use pel::Reference;
use std::cell::RefCell;

pub(crate) struct PayloadContext<'a> {
    input_context: &'a InputContext,
    binding: &'a dyn PayloadBinding,
    payload: RefCell<Option<PelValue>>,
}

impl<'a> PayloadContext<'a> {
    pub fn new(input_context: &'a InputContext, binding: &'a dyn PayloadBinding) -> Self {
        Self {
            input_context,
            binding,
            payload: RefCell::new(None),
        }
    }

    fn do_resolve(&self) -> PelValue {
        let present = self.payload.borrow().is_some();

        if !present {
            let bytes = self.binding.as_bytes();
            let value = match self.input_context.format().unwrap_or(&Format::PlainText) {
                Format::Json => serde_json::from_slice(bytes.as_ref()).unwrap_or(Value::Null),
                Format::PlainText => {
                    Value::String(String::from_utf8_lossy(bytes.as_ref()).to_string())
                }
            };

            self.payload.replace(Some(value.into_pel()));
        }

        self.payload
            .borrow()
            .as_ref()
            .cloned()
            .unwrap_or_else(PelValue::null)
    }
}

impl Context for PayloadContext<'_> {
    fn resolve(&self, symbol: &Symbol) -> PelBinding {
        match self.input_context.format().is_some() && symbol.as_str() == PAYLOAD {
            true => PelBinding::Available(self.do_resolve()),
            false => PelBinding::Unknown,
        }
    }

    fn value_handler(&self, _reference: Reference) -> Option<&dyn ValueHandler> {
        None
    }
}