use super::GO_BLOCK_RE;
use super::go_blocks::{extract_block_parts, push_char_at};
use super::string_lit::{copy_raw_string, is_string_delim};
pub(super) fn strip_dollar_vars(template: &str) -> String {
GO_BLOCK_RE
.replace_all(template, |caps: ®ex::Captures| {
let block = &caps[0];
let bytes = block.as_bytes();
let mut result = String::with_capacity(block.len());
let mut i = 0;
while i < bytes.len() {
if is_string_delim(bytes[i]) {
i = copy_raw_string(&mut result, block, i);
continue;
}
if bytes[i] == b'$'
&& i + 1 < bytes.len()
&& (bytes[i + 1].is_ascii_alphabetic() || bytes[i + 1] == b'_')
{
i += 1;
continue;
}
i += push_char_at(&mut result, block, i);
}
result
})
.to_string()
}
pub(super) fn preprocess_strip_dots(template: &str) -> String {
GO_BLOCK_RE
.replace_all(template, |caps: ®ex::Captures| {
let block = &caps[0];
let (open, inner, close) = extract_block_parts(block);
let mut result = String::with_capacity(block.len());
result.push_str(open);
let bytes = inner.as_bytes();
let mut i = 0;
while i < bytes.len() {
if is_string_delim(bytes[i]) {
i = copy_raw_string(&mut result, inner, i);
continue;
}
if bytes[i] == b'.'
&& i + 1 < bytes.len()
&& (bytes[i + 1].is_ascii_alphanumeric() || bytes[i + 1] == b'_')
{
let prev_is_word = i > 0
&& (bytes[i - 1].is_ascii_alphanumeric()
|| bytes[i - 1] == b'_'
|| bytes[i - 1] == b'?'
|| bytes[i - 1] == b']');
if prev_is_word {
result.push('.');
}
i += 1;
} else {
i += push_char_at(&mut result, inner, i);
}
}
result.push_str(close);
result
})
.to_string()
}
fn ends_with_path_head(out: &str) -> bool {
let bytes = out.as_bytes();
let mut k = bytes.len();
if k > 0 && bytes[k - 1] == b'?' {
k -= 1;
}
if k == 0 {
return false;
}
match bytes[k - 1] {
b']' | b')' => true,
c if c.is_ascii_alphanumeric() || c == b'_' => {
let end = k;
while k > 0 && (bytes[k - 1].is_ascii_alphanumeric() || bytes[k - 1] == b'_') {
k -= 1;
}
bytes[k..end].iter().any(|c| !c.is_ascii_digit())
}
_ => false,
}
}
pub(super) fn rewrite_numeric_index_segments(template: &str) -> String {
GO_BLOCK_RE
.replace_all(template, |caps: ®ex::Captures| {
let block = &caps[0];
let (open, inner, close) = extract_block_parts(block);
let mut result = String::with_capacity(block.len());
result.push_str(open);
let bytes = inner.as_bytes();
let mut i = 0;
while i < bytes.len() {
if is_string_delim(bytes[i]) {
i = copy_raw_string(&mut result, inner, i);
continue;
}
if bytes[i] == b'.' && i + 1 < bytes.len() && bytes[i + 1].is_ascii_digit() {
let mut j = i + 1;
while j < bytes.len() && bytes[j].is_ascii_digit() {
j += 1;
}
let ends_at_boundary =
j >= bytes.len() || (!bytes[j].is_ascii_alphabetic() && bytes[j] != b'_');
if ends_at_boundary && ends_with_path_head(&result) {
result.push('[');
result.push_str(&inner[i + 1..j]);
result.push(']');
i = j;
continue;
}
}
i += push_char_at(&mut result, inner, i);
}
result.push_str(close);
result
})
.to_string()
}