#![expect(
dead_code,
reason = "包级解析辅助将在后续 StandardExpressionParser 主链中消费"
)]
use std::sync::Arc;
use crate::context::IExpressionContext;
use crate::util::{Utf16String, ValidateError};
use super::{
IStandardExpression, LiteralValue, StandardExpressionError, StandardExpressionExecutionContext,
StandardExpressionResult, TemplateValue, TokenError,
};
pub struct TextLiteralExpression {
value: Arc<LiteralValue>,
}
impl TextLiteralExpression {
pub const ESCAPE_PREFIX: u16 = b'\\' as u16;
pub const DELIMITER: u16 = b'\'' as u16;
pub fn new(value: Option<&Utf16String>) -> Result<Self, ValidateError> {
let value = value.ok_or_else(|| ValidateError::IllegalArgument {
message: Some("Value cannot be null".to_owned()),
})?;
Ok(Self {
value: Arc::new(LiteralValue::new(Some(unwrap_literal(value)))),
})
}
pub fn get_value(&self) -> &LiteralValue {
self.value.as_ref()
}
pub(crate) fn parse_text_literal_expression(input: &Utf16String) -> Self {
Self::new(Some(input)).expect("non-null parser input")
}
pub fn wrap_string_into_literal(value: Option<&Utf16String>) -> Option<Utf16String> {
let value = value?;
let quote_count = value
.as_utf16()
.iter()
.filter(|unit| **unit == Self::DELIMITER)
.count();
let mut units = Vec::with_capacity(value.len() + quote_count + 2);
units.push(Self::DELIMITER);
for unit in value.as_utf16() {
if *unit == Self::DELIMITER {
units.push(Self::ESCAPE_PREFIX);
}
units.push(*unit);
}
units.push(Self::DELIMITER);
Some(Utf16String::from_utf16(units))
}
pub(crate) fn is_delimiter_escaped(
input: Option<&Utf16String>,
position: i32,
) -> Result<bool, TokenError> {
let input = input.ok_or(TokenError::NullPointer)?;
let position = usize::try_from(position)
.map_err(|_| TokenError::StringIndexOutOfBounds { position })?;
if position >= input.len() {
return Err(TokenError::StringIndexOutOfBounds {
position: position as i32,
});
}
if position == 0 || input.as_utf16()[position - 1] != Self::ESCAPE_PREFIX {
return Ok(false);
}
let mut current = position;
let mut odd = false;
while current > 0 {
current -= 1;
if input.as_utf16()[current] == Self::ESCAPE_PREFIX {
odd = !odd;
} else {
return Ok(odd);
}
}
Ok(odd)
}
}
impl IStandardExpression for TextLiteralExpression {
fn get_string_representation(&self) -> StandardExpressionResult<Utf16String> {
let value = self
.value
.get_value()
.ok_or_else(|| Box::new(TokenError::NullPointer) as StandardExpressionError)?;
Ok(Self::wrap_string_into_literal(Some(value)).expect("non-null literal value"))
}
fn execute_with_context(
&self,
_context: &dyn IExpressionContext,
_expression_context: &'static StandardExpressionExecutionContext,
) -> StandardExpressionResult<Option<Arc<TemplateValue>>> {
Ok(self
.value
.get_value()
.cloned()
.map(TemplateValue::string)
.map(Arc::new))
}
fn execute_raw(
&self,
_context: &dyn IExpressionContext,
_expression_context: &'static StandardExpressionExecutionContext,
) -> StandardExpressionResult<Option<Arc<TemplateValue>>> {
Ok(Some(Arc::new(TemplateValue::Literal(Arc::clone(
&self.value,
)))))
}
fn is_text_literal_expression(&self) -> bool {
true
}
}
impl super::SimpleExpression for TextLiteralExpression {}
fn unwrap_literal(input: &Utf16String) -> Utf16String {
let units = input.as_utf16();
if units.len() > 1
&& units[0] == TextLiteralExpression::DELIMITER
&& units[units.len() - 1] == TextLiteralExpression::DELIMITER
{
return unescape_literal(&units[1..units.len() - 1]);
}
input.clone()
}
fn unescape_literal(text: &[u16]) -> Utf16String {
let mut result = Vec::with_capacity(text.len());
let mut position = 0;
while position < text.len() {
let unit = text[position];
if unit == TextLiteralExpression::ESCAPE_PREFIX && position + 1 < text.len() {
let next = text[position + 1];
if next == TextLiteralExpression::DELIMITER
|| next == TextLiteralExpression::ESCAPE_PREFIX
{
result.push(next);
position += 2;
continue;
}
}
result.push(unit);
position += 1;
}
Utf16String::from_utf16(result)
}