use std::any::Any;
use std::sync::Arc;
pub fn concat_strings(
v1: &Arc<dyn Any + Send + Sync>,
v2: &Arc<dyn Any + Send + Sync>,
) -> Result<Arc<dyn Any + Send + Sync>, String> {
if let (Ok(arc_str1), Ok(arc_str2)) = (
v1.clone().downcast::<String>(),
v2.clone().downcast::<String>(),
) {
let result = format!("{}{}", *arc_str1, *arc_str2);
return Ok(Arc::new(result) as Arc<dyn Any + Send + Sync>);
}
Err(format!(
"Unsupported types for string concatenation: {} + {} (both inputs must be String)",
std::any::type_name_of_val(&**v1),
std::any::type_name_of_val(&**v2)
))
}
pub fn string_length(v: &Arc<dyn Any + Send + Sync>) -> Result<Arc<dyn Any + Send + Sync>, String> {
if let Ok(arc_str) = v.clone().downcast::<String>() {
let length = arc_str.len();
return Ok(Arc::new(length) as Arc<dyn Any + Send + Sync>);
}
Err(format!(
"Unsupported type for string length: {} (input must be String)",
std::any::type_name_of_val(&**v)
))
}
pub fn string_slice(
v: &Arc<dyn Any + Send + Sync>,
start: &Arc<dyn Any + Send + Sync>,
end: &Arc<dyn Any + Send + Sync>,
) -> Result<Arc<dyn Any + Send + Sync>, String> {
let arc_str = v.clone().downcast::<String>().map_err(|_| {
format!(
"Unsupported type for string slice input: {} (input must be String)",
std::any::type_name_of_val(&**v)
)
})?;
let start_idx = if let Ok(arc_usize) = start.clone().downcast::<usize>() {
*arc_usize
} else if let Ok(arc_i32) = start.clone().downcast::<i32>() {
if *arc_i32 < 0 {
return Err("Start index cannot be negative".to_string());
}
*arc_i32 as usize
} else if let Ok(arc_i64) = start.clone().downcast::<i64>() {
if *arc_i64 < 0 {
return Err("Start index cannot be negative".to_string());
}
if *arc_i64 > usize::MAX as i64 {
return Err("Start index too large".to_string());
}
*arc_i64 as usize
} else if let Ok(arc_u32) = start.clone().downcast::<u32>() {
*arc_u32 as usize
} else if let Ok(arc_u64) = start.clone().downcast::<u64>() {
if *arc_u64 > usize::MAX as u64 {
return Err("Start index too large".to_string());
}
*arc_u64 as usize
} else {
return Err(format!(
"Unsupported type for start index: {} (must be numeric)",
std::any::type_name_of_val(&**start)
));
};
let end_idx = if let Ok(arc_usize) = end.clone().downcast::<usize>() {
*arc_usize
} else if let Ok(arc_i32) = end.clone().downcast::<i32>() {
if *arc_i32 < 0 {
return Err("End index cannot be negative".to_string());
}
*arc_i32 as usize
} else if let Ok(arc_i64) = end.clone().downcast::<i64>() {
if *arc_i64 < 0 {
return Err("End index cannot be negative".to_string());
}
if *arc_i64 > usize::MAX as i64 {
return Err("End index too large".to_string());
}
*arc_i64 as usize
} else if let Ok(arc_u32) = end.clone().downcast::<u32>() {
*arc_u32 as usize
} else if let Ok(arc_u64) = end.clone().downcast::<u64>() {
if *arc_u64 > usize::MAX as u64 {
return Err("End index too large".to_string());
}
*arc_u64 as usize
} else {
return Err(format!(
"Unsupported type for end index: {} (must be numeric)",
std::any::type_name_of_val(&**end)
));
};
if start_idx > end_idx {
return Err(format!(
"Invalid index range: start ({}) > end ({})",
start_idx, end_idx
));
}
let char_count = arc_str.chars().count();
if start_idx > char_count {
return Err(format!(
"Start index ({}) out of bounds for string of length {} (character count)",
start_idx, char_count
));
}
if end_idx > char_count {
return Err(format!(
"End index ({}) out of bounds for string of length {} (character count)",
end_idx, char_count
));
}
let mut start_byte = 0;
let mut end_byte = arc_str.len();
for (char_idx, (byte_idx, _)) in arc_str.char_indices().enumerate() {
if char_idx == start_idx {
start_byte = byte_idx;
}
if char_idx == end_idx {
end_byte = byte_idx;
break;
}
}
if end_idx == char_count {
end_byte = arc_str.len();
}
let result = arc_str[start_byte..end_byte].to_string();
Ok(Arc::new(result) as Arc<dyn Any + Send + Sync>)
}
pub fn string_replace(
v: &Arc<dyn Any + Send + Sync>,
pattern: &Arc<dyn Any + Send + Sync>,
replacement: &Arc<dyn Any + Send + Sync>,
) -> Result<Arc<dyn Any + Send + Sync>, String> {
let arc_str = v.clone().downcast::<String>().map_err(|_| {
format!(
"Unsupported type for string replace input: {} (input must be String)",
std::any::type_name_of_val(&**v)
)
})?;
let arc_pattern = pattern.clone().downcast::<String>().map_err(|_| {
format!(
"Unsupported type for pattern: {} (pattern must be String)",
std::any::type_name_of_val(&**pattern)
)
})?;
let arc_replacement = replacement.clone().downcast::<String>().map_err(|_| {
format!(
"Unsupported type for replacement: {} (replacement must be String)",
std::any::type_name_of_val(&**replacement)
)
})?;
let result = arc_str.replace(&*arc_pattern, &arc_replacement);
Ok(Arc::new(result) as Arc<dyn Any + Send + Sync>)
}
pub fn string_split(
v: &Arc<dyn Any + Send + Sync>,
delimiter: &Arc<dyn Any + Send + Sync>,
) -> Result<Arc<dyn Any + Send + Sync>, String> {
let arc_str = v.clone().downcast::<String>().map_err(|_| {
format!(
"Unsupported type for string split input: {} (input must be String)",
std::any::type_name_of_val(&**v)
)
})?;
let arc_delimiter = delimiter.clone().downcast::<String>().map_err(|_| {
format!(
"Unsupported type for delimiter: {} (delimiter must be String)",
std::any::type_name_of_val(&**delimiter)
)
})?;
let parts: Vec<Arc<dyn Any + Send + Sync>> = arc_str
.split(&*arc_delimiter)
.map(|s| Arc::new(s.to_string()) as Arc<dyn Any + Send + Sync>)
.collect();
Ok(Arc::new(parts) as Arc<dyn Any + Send + Sync>)
}
pub fn string_join(
v: &Arc<dyn Any + Send + Sync>,
delimiter: &Arc<dyn Any + Send + Sync>,
) -> Result<Arc<dyn Any + Send + Sync>, String> {
let arc_vec = v
.clone()
.downcast::<Vec<Arc<dyn Any + Send + Sync>>>()
.map_err(|_| {
format!(
"Unsupported type for string join input: {} (input must be Vec<Arc<dyn Any + Send + Sync>>)",
std::any::type_name_of_val(&**v)
)
})?;
let arc_delimiter = delimiter.clone().downcast::<String>().map_err(|_| {
format!(
"Unsupported type for delimiter: {} (delimiter must be String)",
std::any::type_name_of_val(&**delimiter)
)
})?;
let mut parts = Vec::new();
for (idx, item) in arc_vec.iter().enumerate() {
let arc_str = item.clone().downcast::<String>().map_err(|_| {
format!(
"Unsupported type for array element at index {}: {} (all elements must be String)",
idx,
std::any::type_name_of_val(&**item)
)
})?;
parts.push((*arc_str).clone());
}
let result = parts.join(&*arc_delimiter);
Ok(Arc::new(result) as Arc<dyn Any + Send + Sync>)
}
pub fn string_contains(
v: &Arc<dyn Any + Send + Sync>,
substring: &Arc<dyn Any + Send + Sync>,
) -> Result<Arc<dyn Any + Send + Sync>, String> {
let arc_str = v.clone().downcast::<String>().map_err(|_| {
format!(
"Unsupported type for string contains input: {} (input must be String)",
std::any::type_name_of_val(&**v)
)
})?;
let arc_substring = substring.clone().downcast::<String>().map_err(|_| {
format!(
"Unsupported type for substring: {} (substring must be String)",
std::any::type_name_of_val(&**substring)
)
})?;
let result = arc_str.contains(&*arc_substring);
Ok(Arc::new(result) as Arc<dyn Any + Send + Sync>)
}
pub fn string_starts_with(
v: &Arc<dyn Any + Send + Sync>,
prefix: &Arc<dyn Any + Send + Sync>,
) -> Result<Arc<dyn Any + Send + Sync>, String> {
let arc_str = v.clone().downcast::<String>().map_err(|_| {
format!(
"Unsupported type for string starts_with input: {} (input must be String)",
std::any::type_name_of_val(&**v)
)
})?;
let arc_prefix = prefix.clone().downcast::<String>().map_err(|_| {
format!(
"Unsupported type for prefix: {} (prefix must be String)",
std::any::type_name_of_val(&**prefix)
)
})?;
let result = arc_str.starts_with(&*arc_prefix);
Ok(Arc::new(result) as Arc<dyn Any + Send + Sync>)
}
pub fn string_ends_with(
v: &Arc<dyn Any + Send + Sync>,
suffix: &Arc<dyn Any + Send + Sync>,
) -> Result<Arc<dyn Any + Send + Sync>, String> {
let arc_str = v.clone().downcast::<String>().map_err(|_| {
format!(
"Unsupported type for string ends_with input: {} (input must be String)",
std::any::type_name_of_val(&**v)
)
})?;
let arc_suffix = suffix.clone().downcast::<String>().map_err(|_| {
format!(
"Unsupported type for suffix: {} (suffix must be String)",
std::any::type_name_of_val(&**suffix)
)
})?;
let result = arc_str.ends_with(&*arc_suffix);
Ok(Arc::new(result) as Arc<dyn Any + Send + Sync>)
}
pub fn string_match(
v: &Arc<dyn Any + Send + Sync>,
pattern: &Arc<dyn Any + Send + Sync>,
) -> Result<Arc<dyn Any + Send + Sync>, String> {
let arc_str = v.clone().downcast::<String>().map_err(|_| {
format!(
"Unsupported type for string match input: {} (input must be String)",
std::any::type_name_of_val(&**v)
)
})?;
let arc_pattern_str = pattern.clone().downcast::<String>().map_err(|_| {
format!(
"Unsupported type for pattern: {} (pattern must be String)",
std::any::type_name_of_val(&**pattern)
)
})?;
let regex_pattern =
regex::Regex::new(&arc_pattern_str).map_err(|e| format!("Invalid regex pattern: {}", e))?;
let result = regex_pattern.is_match(&arc_str);
Ok(Arc::new(result) as Arc<dyn Any + Send + Sync>)
}
pub fn string_equal(
v1: &Arc<dyn Any + Send + Sync>,
v2: &Arc<dyn Any + Send + Sync>,
) -> Result<Arc<dyn Any + Send + Sync>, String> {
let arc_str1 = v1.clone().downcast::<String>().map_err(|_| {
format!(
"Unsupported type for string equal input 1: {} (input must be String)",
std::any::type_name_of_val(&**v1)
)
})?;
let arc_str2 = v2.clone().downcast::<String>().map_err(|_| {
format!(
"Unsupported type for string equal input 2: {} (input must be String)",
std::any::type_name_of_val(&**v2)
)
})?;
let result = *arc_str1 == *arc_str2;
Ok(Arc::new(result) as Arc<dyn Any + Send + Sync>)
}
pub fn string_case(
v: &Arc<dyn Any + Send + Sync>,
case_type: &Arc<dyn Any + Send + Sync>,
) -> Result<Arc<dyn Any + Send + Sync>, String> {
let arc_str = v.clone().downcast::<String>().map_err(|_| {
format!(
"Unsupported type for string case input: {} (input must be String)",
std::any::type_name_of_val(&**v)
)
})?;
let arc_case_type = case_type.clone().downcast::<String>().map_err(|_| {
format!(
"Unsupported type for case type: {} (case type must be String)",
std::any::type_name_of_val(&**case_type)
)
})?;
let result = match arc_case_type.to_lowercase().as_str() {
"upper" | "uppercase" => arc_str.to_uppercase(),
"lower" | "lowercase" => arc_str.to_lowercase(),
"title" | "titlecase" => {
arc_str
.split_whitespace()
.map(|word| {
let mut chars = word.chars();
match chars.next() {
None => String::new(),
Some(first) => {
first.to_uppercase().collect::<String>() + &chars.as_str().to_lowercase()
}
}
})
.collect::<Vec<_>>()
.join(" ")
}
_ => {
return Err(format!(
"Unsupported case type: {} (must be 'upper', 'lower', or 'title')",
*arc_case_type
));
}
};
Ok(Arc::new(result) as Arc<dyn Any + Send + Sync>)
}
pub fn string_trim(v: &Arc<dyn Any + Send + Sync>) -> Result<Arc<dyn Any + Send + Sync>, String> {
let arc_str = v.clone().downcast::<String>().map_err(|_| {
format!(
"Unsupported type for string trim input: {} (input must be String)",
std::any::type_name_of_val(&**v)
)
})?;
let result = arc_str.trim().to_string();
Ok(Arc::new(result) as Arc<dyn Any + Send + Sync>)
}
pub fn string_pad(
v: &Arc<dyn Any + Send + Sync>,
length: &Arc<dyn Any + Send + Sync>,
padding: &Arc<dyn Any + Send + Sync>,
side: &Arc<dyn Any + Send + Sync>,
) -> Result<Arc<dyn Any + Send + Sync>, String> {
let arc_str = v.clone().downcast::<String>().map_err(|_| {
format!(
"Unsupported type for string pad input: {} (input must be String)",
std::any::type_name_of_val(&**v)
)
})?;
let get_usize = |val: &Arc<dyn Any + Send + Sync>, name: &str| -> Result<usize, String> {
if let Ok(arc_usize) = val.clone().downcast::<usize>() {
Ok(*arc_usize)
} else if let Ok(arc_i32) = val.clone().downcast::<i32>() {
if *arc_i32 < 0 {
return Err(format!("{} cannot be negative", name));
}
(*arc_i32)
.try_into()
.map_err(|_| format!("{} too large", name))
} else if let Ok(arc_i64) = val.clone().downcast::<i64>() {
if *arc_i64 < 0 {
return Err(format!("{} cannot be negative", name));
}
(*arc_i64)
.try_into()
.map_err(|_| format!("{} too large", name))
} else if let Ok(arc_u32) = val.clone().downcast::<u32>() {
(*arc_u32)
.try_into()
.map_err(|_| format!("{} too large", name))
} else if let Ok(arc_u64) = val.clone().downcast::<u64>() {
(*arc_u64)
.try_into()
.map_err(|_| format!("{} too large", name))
} else {
Err(format!(
"Unsupported type for {}: {} (must be numeric)",
name,
std::any::type_name_of_val(&**val)
))
}
};
let target_length = get_usize(length, "length")?;
let padding_char = if let Ok(arc_pad_str) = padding.clone().downcast::<String>() {
let pad_str = &*arc_pad_str;
if pad_str.is_empty() {
' '
} else {
pad_str.chars().next().unwrap_or(' ')
}
} else if let Ok(arc_char) = padding.clone().downcast::<char>() {
*arc_char
} else {
' ' };
let side_str = if let Ok(arc_side) = side.clone().downcast::<String>() {
arc_side.to_lowercase()
} else {
"right".to_string() };
let current_len = arc_str.chars().count();
if current_len >= target_length {
return Ok(arc_str.clone());
}
let pad_count = target_length - current_len;
let pad_str: String = std::iter::repeat_n(padding_char, pad_count).collect();
let result = match side_str.as_str() {
"left" => format!("{}{}", pad_str, arc_str),
"right" => format!("{}{}", arc_str, pad_str),
"center" => {
let left_pad = pad_count / 2;
let right_pad = pad_count - left_pad;
let left_str: String = std::iter::repeat_n(padding_char, left_pad).collect();
let right_str: String = std::iter::repeat_n(padding_char, right_pad).collect();
format!("{}{}{}", left_str, arc_str, right_str)
}
_ => {
return Err(format!(
"Unsupported padding side: {} (must be 'left', 'right', or 'center')",
side_str
));
}
};
Ok(Arc::new(result) as Arc<dyn Any + Send + Sync>)
}
pub fn append_suffix(
base: &Arc<dyn Any + Send + Sync>,
suffix: &Arc<dyn Any + Send + Sync>,
) -> Result<Arc<dyn Any + Send + Sync>, String> {
if let (Ok(arc_str1), Ok(arc_str2)) = (
base.clone().downcast::<String>(),
suffix.clone().downcast::<String>(),
) {
let result = format!("{}{}", *arc_str1, *arc_str2);
return Ok(Arc::new(result) as Arc<dyn Any + Send + Sync>);
}
Err(format!(
"Unsupported types for string append: {} + {} (both inputs must be String)",
std::any::type_name_of_val(&**base),
std::any::type_name_of_val(&**suffix)
))
}
pub fn capitalize_string(
v: &Arc<dyn Any + Send + Sync>,
) -> Result<Arc<dyn Any + Send + Sync>, String> {
let arc_str = v.clone().downcast::<String>().map_err(|_| {
format!(
"Unsupported type for string capitalize input: {} (input must be String)",
std::any::type_name_of_val(&**v)
)
})?;
let mut chars = arc_str.chars();
let result = if let Some(first_char) = chars.next() {
first_char.to_uppercase().collect::<String>() + chars.as_str()
} else {
(*arc_str).clone()
};
Ok(Arc::new(result) as Arc<dyn Any + Send + Sync>)
}
pub fn lowercase_string(
v: &Arc<dyn Any + Send + Sync>,
) -> Result<Arc<dyn Any + Send + Sync>, String> {
let arc_str = v.clone().downcast::<String>().map_err(|_| {
format!(
"Unsupported type for string lowercase input: {} (input must be String)",
std::any::type_name_of_val(&**v)
)
})?;
let result = arc_str.to_lowercase();
Ok(Arc::new(result) as Arc<dyn Any + Send + Sync>)
}
pub fn uppercase_string(
v: &Arc<dyn Any + Send + Sync>,
) -> Result<Arc<dyn Any + Send + Sync>, String> {
let arc_str = v.clone().downcast::<String>().map_err(|_| {
format!(
"Unsupported type for string uppercase input: {} (input must be String)",
std::any::type_name_of_val(&**v)
)
})?;
let result = arc_str.to_uppercase();
Ok(Arc::new(result) as Arc<dyn Any + Send + Sync>)
}
pub fn char_at(
string_value: &Arc<dyn Any + Send + Sync>,
index_value: &Arc<dyn Any + Send + Sync>,
) -> Result<Arc<dyn Any + Send + Sync>, String> {
let arc_str = string_value.clone().downcast::<String>().map_err(|_| {
format!(
"Unsupported type for string char_at input: {} (input must be String)",
std::any::type_name_of_val(&**string_value)
)
})?;
let index = if let Ok(idx) = index_value.clone().downcast::<usize>() {
*idx
} else if let Ok(idx) = index_value.clone().downcast::<u32>() {
*idx as usize
} else if let Ok(idx) = index_value.clone().downcast::<u64>() {
*idx as usize
} else if let Ok(idx) = index_value.clone().downcast::<i32>() {
if *idx < 0 {
return Err("Index cannot be negative".to_string());
}
*idx as usize
} else if let Ok(idx) = index_value.clone().downcast::<i64>() {
if *idx < 0 {
return Err("Index cannot be negative".to_string());
}
*idx as usize
} else {
return Err(format!(
"Unsupported type for char_at index: {} (index must be a non-negative integer)",
std::any::type_name_of_val(&**index_value)
));
};
let chars: Vec<char> = arc_str.chars().collect();
if index >= chars.len() {
return Err(format!(
"Index {} is out of bounds for string of length {} (character count)",
index,
chars.len()
));
}
let result = chars[index].to_string();
Ok(Arc::new(result) as Arc<dyn Any + Send + Sync>)
}
pub fn prepend_prefix(
prefix: &Arc<dyn Any + Send + Sync>,
base: &Arc<dyn Any + Send + Sync>,
) -> Result<Arc<dyn Any + Send + Sync>, String> {
if let (Ok(arc_prefix), Ok(arc_base)) = (
prefix.clone().downcast::<String>(),
base.clone().downcast::<String>(),
) {
let result = format!("{}{}", *arc_prefix, *arc_base);
return Ok(Arc::new(result) as Arc<dyn Any + Send + Sync>);
}
Err(format!(
"Unsupported types for string prepend: {} + {} (both inputs must be String)",
std::any::type_name_of_val(&**prefix),
std::any::type_name_of_val(&**base)
))
}
pub fn format_string(
template: &Arc<dyn Any + Send + Sync>,
value: &Arc<dyn Any + Send + Sync>,
) -> Result<Arc<dyn Any + Send + Sync>, String> {
let arc_template = template.clone().downcast::<String>().map_err(|_| {
format!(
"Unsupported type for template: {} (template must be String)",
std::any::type_name_of_val(&**template)
)
})?;
let value_str = if let Ok(arc_str) = value.clone().downcast::<String>() {
(*arc_str).clone()
} else if let Ok(arc_i32) = value.clone().downcast::<i32>() {
arc_i32.to_string()
} else if let Ok(arc_i64) = value.clone().downcast::<i64>() {
arc_i64.to_string()
} else if let Ok(arc_u32) = value.clone().downcast::<u32>() {
arc_u32.to_string()
} else if let Ok(arc_u64) = value.clone().downcast::<u64>() {
arc_u64.to_string()
} else if let Ok(arc_f64) = value.clone().downcast::<f64>() {
arc_f64.to_string()
} else if let Ok(arc_bool) = value.clone().downcast::<bool>() {
arc_bool.to_string()
} else {
format!("{:?}", value)
};
let result = arc_template.replace("{}", &value_str);
Ok(Arc::new(result) as Arc<dyn Any + Send + Sync>)
}
pub fn string_index_of(
v: &Arc<dyn Any + Send + Sync>,
substring: &Arc<dyn Any + Send + Sync>,
) -> Result<Arc<dyn Any + Send + Sync>, String> {
let arc_str = v.clone().downcast::<String>().map_err(|_| {
format!(
"Unsupported type for string index_of input: {} (input must be String)",
std::any::type_name_of_val(&**v)
)
})?;
let arc_substring = substring.clone().downcast::<String>().map_err(|_| {
format!(
"Unsupported type for substring: {} (substring must be String)",
std::any::type_name_of_val(&**substring)
)
})?;
let index = arc_str
.find(&*arc_substring)
.map(|i| i as i64)
.unwrap_or(-1);
Ok(Arc::new(index) as Arc<dyn Any + Send + Sync>)
}
pub fn string_last_index_of(
v: &Arc<dyn Any + Send + Sync>,
substring: &Arc<dyn Any + Send + Sync>,
) -> Result<Arc<dyn Any + Send + Sync>, String> {
let arc_str = v.clone().downcast::<String>().map_err(|_| {
format!(
"Unsupported type for string last_index_of input: {} (input must be String)",
std::any::type_name_of_val(&**v)
)
})?;
let arc_substring = substring.clone().downcast::<String>().map_err(|_| {
format!(
"Unsupported type for substring: {} (substring must be String)",
std::any::type_name_of_val(&**substring)
)
})?;
let index = arc_str
.rfind(&*arc_substring)
.map(|i| i as i64)
.unwrap_or(-1);
Ok(Arc::new(index) as Arc<dyn Any + Send + Sync>)
}
pub fn string_reverse(
v: &Arc<dyn Any + Send + Sync>,
) -> Result<Arc<dyn Any + Send + Sync>, String> {
let arc_str = v.clone().downcast::<String>().map_err(|_| {
format!(
"Unsupported type for string reverse input: {} (input must be String)",
std::any::type_name_of_val(&**v)
)
})?;
let result: String = arc_str.chars().rev().collect();
Ok(Arc::new(result) as Arc<dyn Any + Send + Sync>)
}