53 lines
1.4 KiB
Rust
53 lines
1.4 KiB
Rust
use bytecount::count;
|
|
use memchr::memchr_iter;
|
|
|
|
#[inline]
|
|
pub(crate) fn parse(text: &str, marker: u8) -> Option<(&str, &str)> {
|
|
debug_assert!(text.len() >= 3);
|
|
|
|
let bytes = text.as_bytes();
|
|
|
|
if bytes[1].is_ascii_whitespace() {
|
|
return None;
|
|
}
|
|
|
|
for i in memchr_iter(marker, bytes).skip(1) {
|
|
if count(&bytes[1..i], b'\n') >= 2 {
|
|
break;
|
|
} else if validate_marker(i, text) {
|
|
return Some((&text[i + 1..], &text[1..i]));
|
|
}
|
|
}
|
|
|
|
None
|
|
}
|
|
|
|
fn validate_marker(pos: usize, text: &str) -> bool {
|
|
if text.as_bytes()[pos - 1].is_ascii_whitespace() {
|
|
false
|
|
} else if let Some(&post) = text.as_bytes().get(pos + 1) {
|
|
match post {
|
|
b' ' | b'-' | b'.' | b',' | b':' | b'!' | b'?' | b'\'' | b'\n' | b')' | b'}' => true,
|
|
_ => false,
|
|
}
|
|
} else {
|
|
true
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
#[test]
|
|
fn parse() {
|
|
use super::parse;
|
|
|
|
assert_eq!(parse("*bold*", b'*'), Some(("", "bold")));
|
|
assert_eq!(parse("*bo*ld*", b'*'), Some(("", "bo*ld")));
|
|
assert_eq!(parse("*bo\nld*", b'*'), Some(("", "bo\nld")));
|
|
assert_eq!(parse("*bold*a", b'*'), None);
|
|
assert_eq!(parse("*bold*", b'/'), None);
|
|
assert_eq!(parse("*bold *", b'*'), None);
|
|
assert_eq!(parse("* bold*", b'*'), None);
|
|
assert_eq!(parse("*b\nol\nd*", b'*'), None);
|
|
}
|
|
}
|