aboutsummaryrefslogtreecommitdiffstats
path: root/src/util/encode.rs
diff options
context:
space:
mode:
authorLibravatar Titus Wormer <tituswormer@gmail.com>2022-07-20 17:19:17 +0200
committerLibravatar Titus Wormer <tituswormer@gmail.com>2022-07-20 17:19:17 +0200
commita820d849c3e20a1d72137072d70a7c8e00306f98 (patch)
treec2916ab31d6d481e0b53a06aa9b95dfcddd4163f /src/util/encode.rs
parent7894ec75a7070591c3499fce1f409563c4edc7d7 (diff)
downloadmarkdown-rs-a820d849c3e20a1d72137072d70a7c8e00306f98.tar.gz
markdown-rs-a820d849c3e20a1d72137072d70a7c8e00306f98.tar.bz2
markdown-rs-a820d849c3e20a1d72137072d70a7c8e00306f98.zip
Refactor to improve allocation around strings
Diffstat (limited to 'src/util/encode.rs')
-rw-r--r--src/util/encode.rs50
1 files changed, 22 insertions, 28 deletions
diff --git a/src/util/encode.rs b/src/util/encode.rs
index a3bd589..965ea5c 100644
--- a/src/util/encode.rs
+++ b/src/util/encode.rs
@@ -20,37 +20,31 @@
/// ## References
///
/// * [`micromark-util-encode` in `micromark`](https://github.com/micromark/micromark/tree/main/packages/micromark-util-encode)
-pub fn encode(value: &str) -> String {
- let mut result: Vec<&str> = vec![];
- let mut start = 0;
- let mut index = 0;
+pub fn encode<S: Into<String>>(value: S) -> String {
+ let mut value = value.into();
- for byte in value.bytes() {
- if let Some(replacement) = match byte {
- b'&' => Some("&amp;"),
- b'"' => Some("&quot;"),
- b'<' => Some("&lt;"),
- b'>' => Some("&gt;"),
- _ => None,
- } {
- if start != index {
- result.push(&value[start..index]);
- }
+ // It’ll grow a bit bigger for each dangerous character.
+ let mut result = String::with_capacity(value.len());
- result.push(replacement);
- start = index + 1;
- }
-
- index += 1;
+ while let Some(indice) = value.find(check) {
+ let after = value.split_off(indice + 1);
+ let dangerous = value.pop().unwrap();
+ result.push_str(&value);
+ result.push_str(match dangerous {
+ '&' => "&amp;",
+ '"' => "&quot;",
+ '<' => "&lt;",
+ '>' => "&gt;",
+ _ => unreachable!("xxx"),
+ });
+ value = after;
}
- if start == 0 {
- value.to_string()
- } else {
- if start < index {
- result.push(&value[start..index]);
- }
+ result.push_str(&value);
- result.join("")
- }
+ result
+}
+
+fn check(char: char) -> bool {
+ matches!(char, '&' | '"' | '<' | '>')
}