use std::fmt::{Display, Formatter};
use serde::de::Visitor;
use serde::{Deserialize, Deserializer};
use pel::expression::Expression as PelExpression;
use pel::parser::{Parser, ParsingUnitError};
#[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)
}
}