pub fn escape_xml_text(input: &str) -> String {
let mut escaped = String::with_capacity(input.len());
for ch in input.chars() {
match ch {
'&' => escaped.push_str("&"),
'<' => escaped.push_str("<"),
'>' => escaped.push_str(">"),
'"' => escaped.push_str("""),
'\'' => escaped.push_str("'"),
_ => escaped.push(ch),
}
}
escaped
}
#[inline]
pub fn escape_xml_attribute(input: &str) -> String {
escape_xml_text(input)
}
pub fn escape_yaml_string(input: &str) -> String {
let escaped = input.replace('\\', "\\\\").replace('"', "\\\"");
format!("\"{}\"", escaped)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_escape_xml_text_ampersand() {
assert_eq!(escape_xml_text("foo & bar"), "foo & bar");
assert_eq!(escape_xml_text("&&&"), "&&&");
}
#[test]
fn test_escape_xml_text_less_than() {
assert_eq!(escape_xml_text("a < b"), "a < b");
assert_eq!(escape_xml_text("<tag>"), "<tag>");
}
#[test]
fn test_escape_xml_text_greater_than() {
assert_eq!(escape_xml_text("a > b"), "a > b");
}
#[test]
fn test_escape_xml_text_quotes() {
assert_eq!(escape_xml_text("say \"hello\""), "say "hello"");
assert_eq!(escape_xml_text("it's"), "it's");
}
#[test]
fn test_escape_xml_text_multiple() {
assert_eq!(
escape_xml_text("<tag attr=\"val\" & more>"),
"<tag attr="val" & more>"
);
}
#[test]
fn test_escape_xml_text_no_escaping_needed() {
assert_eq!(escape_xml_text("hello world"), "hello world");
assert_eq!(escape_xml_text(""), "");
assert_eq!(escape_xml_text("123 abc XYZ"), "123 abc XYZ");
}
#[test]
fn test_escape_xml_text_code_snippet() {
let code = "if (a < b && c > d) { return \"ok\"; }";
let escaped = escape_xml_text(code);
assert!(escaped.contains("<"));
assert!(escaped.contains(">"));
assert!(escaped.contains("&"));
assert!(escaped.contains("""));
}
#[test]
fn test_escape_xml_text_unicode() {
assert_eq!(escape_xml_text("Hello 世界"), "Hello 世界");
assert_eq!(escape_xml_text("Emoji: 🚀"), "Emoji: 🚀");
}
#[test]
fn test_escape_xml_attr_delegates_to_text() {
assert_eq!(escape_xml_attribute("foo & bar"), escape_xml_text("foo & bar"));
assert_eq!(escape_xml_attribute("<tag>"), escape_xml_text("<tag>"));
}
#[test]
fn test_escape_xml_attr_quotes() {
assert_eq!(escape_xml_attribute("value with \"quotes\""), "value with "quotes"");
}
#[test]
fn test_escape_yaml_string_no_escaping() {
assert_eq!(escape_yaml_string("hello"), "\"hello\"");
assert_eq!(escape_yaml_string("Hello World"), "\"Hello World\"");
}
#[test]
fn test_escape_yaml_string_backslash() {
assert_eq!(escape_yaml_string("C:\\temp"), "\"C:\\\\temp\"");
assert_eq!(escape_yaml_string("C:\\temp\\file.txt"), "\"C:\\\\temp\\\\file.txt\"");
assert_eq!(escape_yaml_string("\\n\\t"), "\"\\\\n\\\\t\"");
}
#[test]
fn test_escape_yaml_string_quotes() {
assert_eq!(escape_yaml_string("He said \"hello\""), "\"He said \\\"hello\\\"\"");
assert_eq!(escape_yaml_string("\"quoted\""), "\"\\\"quoted\\\"\"");
}
#[test]
fn test_escape_yaml_string_combined() {
assert_eq!(escape_yaml_string("Path: \"C:\\temp\""), "\"Path: \\\"C:\\\\temp\\\"\"");
assert_eq!(
escape_yaml_string("\"C:\\Program Files\\app\\\""),
"\"\\\"C:\\\\Program Files\\\\app\\\\\\\"\""
);
}
#[test]
fn test_escape_yaml_string_empty() {
assert_eq!(escape_yaml_string(""), "\"\"");
}
#[test]
fn test_escape_yaml_string_unicode() {
assert_eq!(escape_yaml_string("Hello 世界"), "\"Hello 世界\"");
assert_eq!(escape_yaml_string("Emoji: 🚀"), "\"Emoji: 🚀\"");
}
#[test]
fn test_escape_yaml_string_special_yaml_chars() {
assert_eq!(escape_yaml_string("key: value"), "\"key: value\"");
assert_eq!(escape_yaml_string("- item"), "\"- item\"");
assert_eq!(escape_yaml_string("# comment"), "\"# comment\"");
}
}