pub(crate) fn to_title_case(s: &str) -> String {
let mut c = s.chars();
match c.next() {
None => String::new(),
Some(f) => f.to_uppercase().collect::<String>() + c.as_str(),
}
}
pub(crate) fn count_chars_and_cases(string: &str) -> (usize, usize, usize) {
string.chars().fold((0, 0, 0), |(total, lower, upper), c| {
let is_lower = c.is_lowercase();
let is_upper = c.is_uppercase();
(
total + 1,
lower + usize::from(is_lower),
upper + usize::from(is_upper),
)
})
}
#[doc(hidden)] #[derive(Debug, PartialEq, Clone, Copy)]
pub enum MimicAction {
Title,
Uppercase,
Nothing,
}
#[doc(hidden)] pub trait LiteralString {
fn chars(&self) -> (usize, bool, bool);
#[must_use]
fn mimic_case_action(&self, from: &str) -> MimicAction {
let (self_char_count, self_has_lowercase, self_has_uppercase) = self.chars();
if self_has_uppercase || !self_has_lowercase {
return MimicAction::Nothing;
}
let (char_count, lowercase, uppercase) = count_chars_and_cases(from);
if (lowercase == 0 && uppercase != 0)
&& (self_char_count == 1 || char_count > 1)
{
return MimicAction::Uppercase;
}
if uppercase == 1
&& (char_count == 1 || from.chars().next().is_some_and(char::is_uppercase))
{
return MimicAction::Title;
}
MimicAction::Nothing
}
}
pub(crate) fn runtime_format_single_value(template: &str, value: &str) -> Result<String, String> {
let mut result = String::new();
let mut formatted = false;
let mut opened = false;
let mut chars = template.chars();
for c in chars.by_ref() {
match c {
'{' => {
opened = !opened;
if opened {
result.push('{');
}
continue;
}
'}' => {
if opened {
result.pop();
result.push_str(value);
formatted = true;
break;
}
}
_ => {}
}
opened = false;
result.push(c);
}
if !formatted {
return Err("string did not contain {} template".to_owned());
}
Ok(result + chars.as_str())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn runtime_format_formats() {
assert_eq!(runtime_format_single_value("{}", "1").unwrap(), "1");
assert_eq!(runtime_format_single_value(" {}", "2").unwrap(), " 2");
assert_eq!(runtime_format_single_value("{} ", "3").unwrap(), "3 ");
assert_eq!(
runtime_format_single_value(r"\b{start-half}{}\b{end-half}", "world").unwrap(),
r"\b{start-half}world\b{end-half}"
);
}
#[test]
fn runtime_format_escapes() {
assert_eq!(
runtime_format_single_value("{{ {}{{", "1").unwrap(),
"{ 1{{"
);
assert_eq!(runtime_format_single_value("}}}{}", "1").unwrap(), "}}}1");
assert_eq!(runtime_format_single_value("{a}{}", "1").unwrap(), "{a}1");
assert_eq!(runtime_format_single_value("{{{}}}", "1").unwrap(), "{1}}");
assert_eq!(runtime_format_single_value("{}{{{", "1").unwrap(), "1{{{");
}
#[test]
fn runtime_format_requires_replacement() {
assert!(runtime_format_single_value("hello {{", "world").is_err());
}
#[test]
fn runtime_format_unmatched() {
assert!(runtime_format_single_value("}0", "world").is_err());
assert!(runtime_format_single_value("{0", "world").is_err());
}
}