use std::sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard};
use crate::templateresource::{ITemplateResource, TemplateResourceError};
use crate::util::Utf16String;
use crate::{IEngineConfiguration, TemplateMode};
use super::IDecoupledTemplateLogicResolver;
pub struct StandardDecoupledTemplateLogicResolver {
prefix: RwLock<Option<Utf16String>>,
suffix: RwLock<Option<Utf16String>>,
}
impl StandardDecoupledTemplateLogicResolver {
pub const DECOUPLED_TEMPLATE_LOGIC_FILE_SUFFIX: &'static str = ".th.xml";
#[must_use]
pub fn new() -> Self {
Self {
prefix: RwLock::new(None),
suffix: RwLock::new(Some(Utf16String::from_rust_str(
Self::DECOUPLED_TEMPLATE_LOGIC_FILE_SUFFIX,
))),
}
}
#[must_use]
pub fn get_suffix(&self) -> Option<Utf16String> {
read_lock(&self.suffix).clone()
}
pub fn set_suffix(&self, suffix: Option<Utf16String>) {
*write_lock(&self.suffix) = suffix;
}
#[must_use]
pub fn get_prefix(&self) -> Option<Utf16String> {
read_lock(&self.prefix).clone()
}
pub fn set_prefix(&self, prefix: Option<Utf16String>) {
*write_lock(&self.prefix) = prefix;
}
}
impl Default for StandardDecoupledTemplateLogicResolver {
fn default() -> Self {
Self::new()
}
}
impl IDecoupledTemplateLogicResolver for StandardDecoupledTemplateLogicResolver {
fn resolve_decoupled_template_logic(
&self,
_configuration: &dyn IEngineConfiguration,
_owner_template: Option<&Utf16String>,
_template: &Utf16String,
_template_selectors: Option<&[Utf16String]>,
resource: &dyn ITemplateResource,
_template_mode: TemplateMode,
) -> Result<Option<Arc<dyn ITemplateResource>>, TemplateResourceError> {
let prefix = read_lock(&self.prefix);
let suffix = read_lock(&self.suffix);
let base_name = resource.get_base_name();
let relative_location = match (prefix.as_ref(), base_name, suffix.as_ref()) {
(None, None, None) => None,
(prefix, base_name, suffix) => {
let mut value = String::new();
if let Some(prefix) = prefix {
value.push_str(&prefix.to_string_lossy());
}
value.push_str(base_name.as_deref().unwrap_or("null"));
if let Some(suffix) = suffix {
value.push_str(&suffix.to_string_lossy());
}
Some(value)
}
};
resource
.relative(relative_location.as_deref())
.map(|resource| Some(Arc::from(resource)))
}
}
fn read_lock<T>(lock: &RwLock<T>) -> RwLockReadGuard<'_, T> {
lock.read()
.unwrap_or_else(std::sync::PoisonError::into_inner)
}
fn write_lock<T>(lock: &RwLock<T>) -> RwLockWriteGuard<'_, T> {
lock.write()
.unwrap_or_else(std::sync::PoisonError::into_inner)
}