use std::marker::PhantomData;
use crate::types::delimiter::Delimiter;
#[derive(Clone, PartialEq, Eq)]
#[cfg_attr(internal_debug, derive(Debug))]
pub struct Syntax<'a> {
pub(crate) delimiters: Vec<Delimiter>,
pub(crate) patterns: Vec<String>,
_marker: PhantomData<&'a ()>,
}
#[derive(Debug, Clone)]
pub struct SyntaxBuilder<'a> {
expr: Option<(&'a str, &'a str)>,
block: Option<(&'a str, &'a str)>,
comment: Option<(&'a str, &'a str)>,
}
impl Default for Syntax<'_> {
#[inline]
fn default() -> Self {
Syntax::builder()
.expr("{{", "}}")
.block("{%", "%}")
.comment("{#", "#}")
.build()
}
}
#[cfg(not(internal_debug))]
impl std::fmt::Debug for Syntax<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Syntax").finish_non_exhaustive()
}
}
impl<'a> Syntax<'a> {
#[inline]
pub fn builder() -> SyntaxBuilder<'a> {
SyntaxBuilder {
expr: None,
block: None,
comment: None,
}
}
}
impl<'a> SyntaxBuilder<'a> {
#[inline]
pub fn expr(&mut self, begin_expr: &'a str, end_expr: &'a str) -> &mut Self {
assert!(!begin_expr.is_empty() && !end_expr.is_empty());
self.expr = Some((begin_expr, end_expr));
self
}
#[inline]
pub fn block(&mut self, begin_block: &'a str, end_block: &'a str) -> &mut Self {
assert!(!begin_block.is_empty() && !end_block.is_empty());
self.block = Some((begin_block, end_block));
self
}
#[inline]
pub fn comment(&mut self, begin_comment: &'a str, end_comment: &'a str) -> &mut Self {
assert!(!begin_comment.is_empty() && !end_comment.is_empty());
self.comment = Some((begin_comment, end_comment));
self
}
pub fn build(&self) -> Syntax<'a> {
let mut delimiters = Vec::new();
let mut patterns = Vec::new();
let mut push = |delimiter, pattern| {
delimiters.push(delimiter);
patterns.push(pattern);
};
if let Some((begin, end)) = self.expr {
push(Delimiter::BeginExpr, begin.into());
push(Delimiter::EndExpr, end.into());
push(Delimiter::BeginExprTrim, format!("{begin}-"));
push(Delimiter::EndExprTrim, format!("-{end}"));
};
if let Some((begin, end)) = self.block {
push(Delimiter::BeginBlock, begin.into());
push(Delimiter::EndBlock, end.into());
push(Delimiter::BeginBlockTrim, format!("{begin}-"));
push(Delimiter::EndBlockTrim, format!("-{end}"));
}
if let Some((begin, end)) = self.comment {
push(Delimiter::BeginComment, begin.into());
push(Delimiter::EndComment, end.into());
push(Delimiter::BeginCommentTrim, format!("{begin}-"));
push(Delimiter::EndCommentTrim, format!("-{end}"));
}
Syntax {
delimiters,
patterns,
_marker: PhantomData,
}
}
}