use std::sync::{Arc, Weak};
use crate::context::IExpressionContext;
use crate::util::{Utf16String, ValidateError};
use super::{StandardExpressionError, StandardExpressionResult, TemplateValue};
pub struct Ids {
context: Weak<dyn IExpressionContext>,
}
impl Ids {
pub fn new(context: Option<Arc<dyn IExpressionContext>>) -> Result<Self, ValidateError> {
let context = context.ok_or_else(|| ValidateError::IllegalArgument {
message: Some("Context cannot be null".to_owned()),
})?;
if context.as_template_context().is_none() {
return Err(ValidateError::IllegalArgument {
message: Some("Context must implement ITemplateContext".to_owned()),
});
}
Ok(Self {
context: Arc::downgrade(&context),
})
}
pub fn seq(&self, id: Option<&TemplateValue>) -> StandardExpressionResult<Utf16String> {
let id = id_to_string(id)?;
let context = self.context()?;
let value = context
.as_template_context()
.expect("constructor verifies template context")
.get_identifier_sequences()
.get_and_increment_id_seq(Some(&id))
.map_err(|error| Box::new(error) as StandardExpressionError)?;
Ok(append_number(&id, value))
}
pub fn next(&self, id: Option<&TemplateValue>) -> StandardExpressionResult<Utf16String> {
let id = id_to_string(id)?;
let context = self.context()?;
let value = context
.as_template_context()
.expect("constructor verifies template context")
.get_identifier_sequences()
.get_next_id_seq(Some(&id))
.map_err(|error| Box::new(error) as StandardExpressionError)?;
Ok(append_number(&id, value))
}
pub fn prev(&self, id: Option<&TemplateValue>) -> StandardExpressionResult<Utf16String> {
let id = id_to_string(id)?;
let context = self.context()?;
let value = context
.as_template_context()
.expect("constructor verifies template context")
.get_identifier_sequences()
.get_previous_id_seq(Some(&id))
.map_err(|error| Box::new(error) as StandardExpressionError)?;
Ok(append_number(&id, value))
}
fn context(&self) -> StandardExpressionResult<Arc<dyn IExpressionContext>> {
self.context.upgrade().ok_or_else(|| {
Box::new(ValidateError::IllegalArgument {
message: Some("Expression context is no longer available".to_owned()),
}) as StandardExpressionError
})
}
}
fn id_to_string(id: Option<&TemplateValue>) -> StandardExpressionResult<Utf16String> {
id.ok_or_else(|| {
Box::new(ValidateError::IllegalArgument {
message: Some("ID cannot be null".to_owned()),
}) as StandardExpressionError
})?
.to_utf16_string()
.ok_or_else(|| Box::new(crate::expression::TokenError::NullPointer) as StandardExpressionError)
}
fn append_number(id: &Utf16String, value: i32) -> Utf16String {
let mut units = id.as_utf16().to_vec();
units.extend(value.to_string().encode_utf16());
Utf16String::from_utf16(units)
}