74 lines
2.1 KiB
Rust
74 lines
2.1 KiB
Rust
//! XML escaping.
|
|
|
|
/// Escape text for an element's content.
|
|
pub fn text(value: &str) -> String {
|
|
let mut out = String::with_capacity(value.len());
|
|
for ch in value.chars() {
|
|
match ch {
|
|
'&' => out.push_str("&"),
|
|
'<' => out.push_str("<"),
|
|
'>' => out.push_str(">"),
|
|
_ => out.push(ch),
|
|
}
|
|
}
|
|
out
|
|
}
|
|
|
|
/// Escape text for an attribute value, which is always double-quoted here.
|
|
pub fn attr(value: &str) -> String {
|
|
let mut out = String::with_capacity(value.len());
|
|
for ch in value.chars() {
|
|
match ch {
|
|
'&' => out.push_str("&"),
|
|
'<' => out.push_str("<"),
|
|
'>' => out.push_str(">"),
|
|
'"' => out.push_str("""),
|
|
_ => out.push(ch),
|
|
}
|
|
}
|
|
out
|
|
}
|
|
|
|
/// Escape text for WML element content.
|
|
#[cfg(feature = "wml")]
|
|
///
|
|
/// WML reads `$` as the start of a variable reference, so a literal one has to be
|
|
/// doubled; otherwise a handset would substitute something or fail to parse.
|
|
pub fn wml(value: &str) -> String {
|
|
text(value).replace('$', "$$")
|
|
}
|
|
|
|
/// Escape text for a WML attribute value.
|
|
#[cfg(feature = "wml")]
|
|
pub fn wml_attr(value: &str) -> String {
|
|
attr(value).replace('$', "$$")
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn escapes_markup_characters() {
|
|
assert_eq!(text("a & b < c > d"), "a & b < c > d");
|
|
// A quote is only significant inside an attribute, so content keeps it.
|
|
assert_eq!(text("say \"hi\""), "say \"hi\"");
|
|
assert_eq!(attr("say \"hi\" & bye"), "say "hi" & bye");
|
|
}
|
|
|
|
#[test]
|
|
#[cfg(feature = "wml")]
|
|
fn wml_doubles_a_literal_dollar() {
|
|
assert_eq!(wml("Permit fee: $5"), "Permit fee: $$5");
|
|
assert_eq!(wml("a & $b"), "a & $$b");
|
|
assert_eq!(wml_attr("/x?a=1&b=$2"), "/x?a=1&b=$$2");
|
|
// The doubling runs after the markup escape, so an escaped entity is not
|
|
// itself rewritten.
|
|
assert_eq!(wml("<$>"), "<$$>");
|
|
}
|
|
|
|
#[test]
|
|
fn leaves_ordinary_text_alone() {
|
|
assert_eq!(text("plain text 123"), "plain text 123");
|
|
}
|
|
}
|