use std::sync::Arc;
use crate::context::IExpressionContext;
use crate::exceptions::TemplateProcessingException;
use crate::util::{BigDecimalValue, NumberValue, Utf16String, ValidateError};
use super::{
ComplexExpression, IStandardExpression, StandardExpressionExecutionContext,
StandardExpressionResult, TemplateValue,
binary_operation_expression::{literal_unwrapped_string, normalized_null_value},
};
pub struct MinusExpression {
operand: Arc<dyn IStandardExpression>,
}
impl MinusExpression {
pub fn new(operand: Option<Arc<dyn IStandardExpression>>) -> Result<Self, ValidateError> {
operand
.map(|operand| Self { operand })
.ok_or_else(|| ValidateError::IllegalArgument {
message: Some("Operand cannot be null".to_owned()),
})
}
pub fn get_operand(&self) -> &dyn IStandardExpression {
self.operand.as_ref()
}
}
impl IStandardExpression for MinusExpression {
fn get_string_representation(&self) -> StandardExpressionResult<Utf16String> {
let mut units = vec![b'-' as u16];
if self.operand.is_complex() {
units.push(b'(' as u16);
}
units.extend_from_slice(self.operand.get_string_representation()?.as_utf16());
if self.operand.is_complex() {
units.push(b')' as u16);
}
Ok(Utf16String::from_utf16(units))
}
fn execute_with_context(
&self,
context: &dyn IExpressionContext,
execution_context: &'static StandardExpressionExecutionContext,
) -> StandardExpressionResult<Option<Arc<TemplateValue>>> {
let operand = normalized_null_value(
self.operand
.execute_with_context(context, execution_context)?,
);
if let TemplateValue::Number(number) = operand.as_ref() {
let negated = match number {
NumberValue::Byte(value) => NumberValue::Integer(-i32::from(*value)),
NumberValue::Short(value) => NumberValue::Integer(-i32::from(*value)),
NumberValue::Integer(value) => NumberValue::Integer(value.wrapping_neg()),
NumberValue::Long(value) => NumberValue::Long(value.wrapping_neg()),
NumberValue::Float(value) => NumberValue::Float(-value),
NumberValue::Double(value) => NumberValue::Double(-value),
NumberValue::BigInteger(value) => NumberValue::BigInteger(-value),
NumberValue::BigDecimal(value) => {
NumberValue::BigDecimal(value.multiply_java(&BigDecimalValue::parse("-1")?)?)
}
NumberValue::Other {
class_name,
double_value,
} => NumberValue::Other {
class_name: class_name.clone(),
double_value: -double_value,
},
};
return Ok(Some(Arc::new(TemplateValue::Number(negated))));
}
let display = literal_unwrapped_string(operand.as_ref())
.unwrap_or_else(|| Utf16String::from_rust_str("null"))
.to_string_lossy();
Err(Box::new(TemplateProcessingException::new(Some(format!(
"Cannot execute minus: operand is \"{display}\""
)))))
}
fn is_complex(&self) -> bool {
true
}
}
impl ComplexExpression for MinusExpression {}