refactor: cleanup parse function

This commit is contained in:
PoiScript 2019-02-08 21:34:58 +08:00
parent c1154a1853
commit c5b14256f0
25 changed files with 1299 additions and 1234 deletions

View file

@ -1,71 +1,42 @@
use memchr::memchr;
#[cfg_attr(test, derive(PartialEq))]
#[derive(Debug)]
pub struct Link<'a> {
pub path: &'a str,
pub desc: Option<&'a str>,
}
/// returns (link path, link description, offset)
#[inline]
pub fn parse(src: &str) -> Option<(&str, Option<&str>, usize)> {
debug_assert!(src.starts_with("[["));
impl<'a> Link<'a> {
pub fn parse(src: &'a str) -> Option<(Link<'a>, usize)> {
debug_assert!(src.starts_with("[["));
let bytes = src.as_bytes();
let path = memchr(b']', bytes).filter(|&i| {
bytes[2..i]
.iter()
.all(|&c| c != b'<' && c != b'>' && c != b'\n')
})?;
let bytes = src.as_bytes();
let path = memchr(b']', bytes).filter(|&i| {
bytes[2..i]
.iter()
.all(|&c| c != b'<' && c != b'>' && c != b'\n')
})?;
if *bytes.get(path + 1)? == b']' {
Some((&src[2..path], None, path + 2))
} else if bytes[path + 1] == b'[' {
let desc = memchr(b']', &bytes[path + 2..])
.map(|i| i + path + 2)
.filter(|&i| bytes[path + 2..i].iter().all(|&c| c != b'['))?;
expect!(src, desc + 1, b']')?;
if *bytes.get(path + 1)? == b']' {
Some((
Link {
path: &src[2..path],
desc: None,
},
path + 2,
))
} else if bytes[path + 1] == b'[' {
let desc = memchr(b']', &bytes[path + 2..])
.map(|i| i + path + 2)
.filter(|&i| bytes[path + 2..i].iter().all(|&c| c != b'['))?;
expect!(src, desc + 1, b']')?;
Some((
Link {
path: &src[2..path],
desc: Some(&src[path + 2..desc]),
},
desc + 2,
))
} else {
None
}
Some((&src[2..path], Some(&src[path + 2..desc]), desc + 2))
} else {
None
}
}
#[test]
fn parse() {
assert_eq!(
Link::parse("[[#id]]").unwrap(),
(
Link {
path: "#id",
desc: None,
},
"[[#id]]".len()
)
);
assert_eq!(
Link::parse("[[#id][desc]]").unwrap(),
(
Link {
path: "#id",
desc: Some("desc"),
},
"[[#id][desc]]".len()
)
);
assert!(Link::parse("[[#id][desc]").is_none());
#[cfg(test)]
mod tests {
#[test]
fn parse() {
use super::parse;
assert_eq!(parse("[[#id]]").unwrap(), ("#id", None, "[[#id]]".len()));
assert_eq!(
parse("[[#id][desc]]").unwrap(),
("#id", Some("desc"), "[[#id][desc]]".len())
);
assert!(parse("[[#id][desc]").is_none());
}
}