From 75362bd2a888621ba8d07a3045f015286fa80857 Mon Sep 17 00:00:00 2001 From: PoiScript Date: Mon, 14 Jan 2019 14:10:12 +0800 Subject: [PATCH] refactor: utils macros --- src/elements/block.rs | 2 +- src/elements/dyn_block.rs | 2 +- src/elements/fn_def.rs | 2 +- src/elements/keyword.rs | 2 +- src/elements/rule.rs | 2 +- src/objects/cookie.rs | 4 +- src/objects/emphasis.rs | 8 ++-- src/objects/entity.rs | 2 +- src/objects/fn_ref.rs | 2 +- src/objects/inline_call.rs | 10 ++-- src/objects/inline_src.rs | 8 ++-- src/objects/link.rs | 4 +- src/objects/macros.rs | 4 +- src/objects/snippet.rs | 2 +- src/objects/target.rs | 12 ++--- src/utils.rs | 95 +++++++++++++++----------------------- 16 files changed, 70 insertions(+), 91 deletions(-) diff --git a/src/elements/block.rs b/src/elements/block.rs index a482645..972fbf3 100644 --- a/src/elements/block.rs +++ b/src/elements/block.rs @@ -11,7 +11,7 @@ impl Block { let args = eol!(src); let name = until_while!(src, 8, |c| c == b' ' || c == b'\n', |c: u8| c - .is_ascii_alphabetic()); + .is_ascii_alphabetic())?; // TODO: ignore case match let content = src.find(&format!("\n#+END_{}", &src[8..name]))?; let end = eol!(src, content + 1); diff --git a/src/elements/dyn_block.rs b/src/elements/dyn_block.rs index 0c9036a..e8ac9b8 100644 --- a/src/elements/dyn_block.rs +++ b/src/elements/dyn_block.rs @@ -11,7 +11,7 @@ impl DynBlock { let args = eol!(src); let name = until_while!(src, 9, |c| c == b' ' || c == b'\n', |c: u8| c - .is_ascii_alphabetic()); + .is_ascii_alphabetic())?; // TODO: ignore case matching let content = src.find("\n#+END:")?; let end = eol!(src, content + 1); diff --git a/src/elements/fn_def.rs b/src/elements/fn_def.rs index cfa89d2..07c1815 100644 --- a/src/elements/fn_def.rs +++ b/src/elements/fn_def.rs @@ -11,7 +11,7 @@ impl FnDef { pub fn parse(src: &str) -> Option<(&str, &str, usize)> { starts_with!(src, "[fn:"); - let label = until_while!(src, 4, b']', valid_label); + let label = until_while!(src, 4, b']', valid_label)?; if label == 4 { return None; diff --git a/src/elements/keyword.rs b/src/elements/keyword.rs index 6c1ffa2..1ee9fd6 100644 --- a/src/elements/keyword.rs +++ b/src/elements/keyword.rs @@ -9,7 +9,7 @@ impl Keyword { starts_with!(src, "#+"); } - let key = until_while!(src, 2, b':', |c: u8| c.is_ascii_uppercase() || c == b'_'); + let key = until_while!(src, 2, b':', |c: u8| c.is_ascii_uppercase() || c == b'_')?; // includes the eol character let end = src.find('\n').map(|i| i + 1).unwrap_or_else(|| src.len()); diff --git a/src/elements/rule.rs b/src/elements/rule.rs index 27e3b35..287c4bf 100644 --- a/src/elements/rule.rs +++ b/src/elements/rule.rs @@ -5,7 +5,7 @@ pub struct Rule; impl Rule { pub fn parse(src: &str) -> Option { let end = eol!(src); - let leading = until_while!(src, 0, b'-', |c| c == b' ' || c == b'\t'); + let leading = until_while!(src, 0, b'-', |c| c == b' ' || c == b'\t')?; if src[leading..end].chars().all(|c| c == '-') && end - leading > 4 { Some(end) } else { diff --git a/src/objects/cookie.rs b/src/objects/cookie.rs index e93298b..4e13c1d 100644 --- a/src/objects/cookie.rs +++ b/src/objects/cookie.rs @@ -11,7 +11,7 @@ impl<'a> Cookie<'a> { } let num1 = until_while!(src, 1, |c| c == b'%' || c == b'/', |c: u8| c - .is_ascii_digit()); + .is_ascii_digit())?; if src.as_bytes()[num1] == b'%' && *src.as_bytes().get(num1 + 1)? == b']' { Some(( @@ -21,7 +21,7 @@ impl<'a> Cookie<'a> { num1 + 2, )) } else { - let num2 = until_while!(src, num1 + 1, b']', |c: u8| c.is_ascii_digit()); + let num2 = until_while!(src, num1 + 1, b']', |c: u8| c.is_ascii_digit())?; Some(( Cookie { value: &src[0..=num2], diff --git a/src/objects/emphasis.rs b/src/objects/emphasis.rs index 7b2d419..7ec452d 100644 --- a/src/objects/emphasis.rs +++ b/src/objects/emphasis.rs @@ -3,7 +3,7 @@ pub struct Emphasis; impl Emphasis { // TODO: return usize instead of Option pub fn parse(src: &str, marker: u8) -> Option { - expect!(src, 1, |c: u8| !c.is_ascii_whitespace()); + expect!(src, 1, |c: u8| !c.is_ascii_whitespace())?; let mut lines = 0; let end = until_while!(src, 1, marker, |c| { @@ -11,9 +11,9 @@ impl Emphasis { lines += 1; } lines < 2 - }); + })?; - expect!(src, end - 1, |c: u8| !c.is_ascii_whitespace()); + expect!(src, end - 1, |c: u8| !c.is_ascii_whitespace())?; if end < src.len() - 1 { expect!(src, end + 1, |ch| ch == b' ' @@ -26,7 +26,7 @@ impl Emphasis { || ch == b'\'' || ch == b'\n' || ch == b')' - || ch == b'}'); + || ch == b'}')?; } Some(end) diff --git a/src/objects/entity.rs b/src/objects/entity.rs index 1358bda..a4d20c5 100644 --- a/src/objects/entity.rs +++ b/src/objects/entity.rs @@ -7,7 +7,7 @@ impl<'a> Entity<'a> { pub fn parse(src: &'a str) -> Option<(Entity<'a>, usize)> { expect!(src, 0, b'\\')?; - let name = position!(src, 1, |c| !c.is_ascii_alphabetic()); + let name = 0; if src.as_bytes()[name] == b'[' { Some(( diff --git a/src/objects/fn_ref.rs b/src/objects/fn_ref.rs index e4a502a..36e3931 100644 --- a/src/objects/fn_ref.rs +++ b/src/objects/fn_ref.rs @@ -13,7 +13,7 @@ impl<'a> FnRef<'a> { pub fn parse(src: &'a str) -> Option<(FnRef<'a>, usize)> { starts_with!(src, "[fn:"); - let label = until_while!(src, 4, |c| c == b']' || c == b':', valid_label); + let label = until_while!(src, 4, |c| c == b']' || c == b':', valid_label)?; if src.as_bytes()[label] == b':' { let mut pairs = 1; diff --git a/src/objects/inline_call.rs b/src/objects/inline_call.rs index efe8d1b..aa92318 100644 --- a/src/objects/inline_call.rs +++ b/src/objects/inline_call.rs @@ -14,28 +14,28 @@ impl<'a> InlineCall<'a> { starts_with!(src, "call_"); let mut pos = until_while!(src, 5, |c| c == b'[' || c == b'(', |c: u8| c - .is_ascii_graphic()); + .is_ascii_graphic())?; let mut pos_; let name = &src[5..pos]; let inside_header = if src.as_bytes()[pos] == b'[' { pos_ = pos; - pos = until_while!(src, pos, b']', |c: u8| c != b'\n') + 1; - expect!(src, pos, b'('); + pos = until_while!(src, pos, b']', |c: u8| c != b'\n')? + 1; + expect!(src, pos, b'(')?; Some(&src[pos_ + 1..pos - 1]) } else { None }; pos_ = pos; - pos = until_while!(src, pos, b')', |c| c != b'\n'); + pos = until_while!(src, pos, b')', |c| c != b'\n')?; let args = &src[pos_ + 1..pos]; let end_header = if src.len() > pos + 1 && src.as_bytes()[pos + 1] == b'[' { pos_ = pos; pos = until_while!(src, pos_ + 1, |c| c == b']', |c: u8| c != b'\n' - && c != b')'); + && c != b')')?; Some(&src[pos_ + 2..pos]) } else { None diff --git a/src/objects/inline_src.rs b/src/objects/inline_src.rs index c4b2c3c..5482b39 100644 --- a/src/objects/inline_src.rs +++ b/src/objects/inline_src.rs @@ -11,15 +11,15 @@ impl<'a> InlineSrc<'a> { starts_with!(src, "src_"); let lang = until_while!(src, 4, |c| c == b'[' || c == b'{', |c: u8| !c - .is_ascii_whitespace()); + .is_ascii_whitespace())?; if lang == 4 { return None; } if src.as_bytes()[lang] == b'[' { - let option = until_while!(src, lang, b']', |c| c != b'\n'); - let body = until_while!(src, option, b'}', |c| c != b'\n'); + let option = until_while!(src, lang, b']', |c| c != b'\n')?; + let body = until_while!(src, option, b'}', |c| c != b'\n')?; Some(( InlineSrc { @@ -30,7 +30,7 @@ impl<'a> InlineSrc<'a> { body + 1, )) } else { - let body = until_while!(src, lang, b'}', |c| c != b'\n'); + let body = until_while!(src, lang, b'}', |c| c != b'\n')?; Some(( InlineSrc { diff --git a/src/objects/link.rs b/src/objects/link.rs index 10473ee..e9600f2 100644 --- a/src/objects/link.rs +++ b/src/objects/link.rs @@ -11,7 +11,7 @@ impl<'a> Link<'a> { starts_with!(src, "[["); } - let path = until_while!(src, 2, b']', |c| c != b'<' && c != b'>' && c != b'\n'); + let path = until_while!(src, 2, b']', |c| c != b'<' && c != b'>' && c != b'\n')?; if cond_eq!(src, path + 1, b']') { Some(( @@ -22,7 +22,7 @@ impl<'a> Link<'a> { path + 2, )) } else if src.as_bytes()[path + 1] == b'[' { - let desc = until_while!(src, path + 2, b']', |c| c != b'['); + let desc = until_while!(src, path + 2, b']', |c| c != b'[')?; expect!(src, desc + 1, b']')?; Some(( diff --git a/src/objects/macros.rs b/src/objects/macros.rs index 0d97b88..ffc22ef 100644 --- a/src/objects/macros.rs +++ b/src/objects/macros.rs @@ -15,9 +15,9 @@ impl<'a> Macros<'a> { pub fn parse(src: &'a str) -> Option<(Macros<'a>, usize)> { starts_with!(src, "{{{"); - expect!(src, 3, |c: u8| c.is_ascii_alphabetic()); + expect!(src, 3, |c: u8| c.is_ascii_alphabetic())?; - let name = until_while!(src, 3, |c| c == b'}' || c == b'(', valid_name); + let name = until_while!(src, 3, |c| c == b'}' || c == b'(', valid_name)?; if src.as_bytes()[name] == b'}' { expect!(src, name + 1, b'}')?; diff --git a/src/objects/snippet.rs b/src/objects/snippet.rs index 51f4316..0c2ddc4 100644 --- a/src/objects/snippet.rs +++ b/src/objects/snippet.rs @@ -13,7 +13,7 @@ impl<'a> Snippet<'a> { starts_with!(src, "@@"); } - let name = until_while!(src, 2, b':', |c: u8| c.is_ascii_alphanumeric() || c == b'-'); + let name = until_while!(src, 2, b':', |c: u8| c.is_ascii_alphanumeric() || c == b'-')?; if name == 2 { return None; diff --git a/src/objects/target.rs b/src/objects/target.rs index dfc5e8b..e5ca8ec 100644 --- a/src/objects/target.rs +++ b/src/objects/target.rs @@ -9,11 +9,11 @@ impl<'a> RadioTarget<'a> { starts_with!(src, "<<<"); } - expect!(src, 3, |c| c != b' '); + expect!(src, 3, |c| c != b' ')?; - let end = until_while!(src, 3, b'>', |c| c != b'<' && c != b'\n'); + let end = until_while!(src, 3, b'>', |c| c != b'<' && c != b'\n')?; - expect!(src, end - 1, |c| c != b' '); + expect!(src, end - 1, |c| c != b' ')?; expect!(src, end + 1, b'>')?; expect!(src, end + 2, b'>')?; @@ -31,11 +31,11 @@ impl<'a> Target<'a> { starts_with!(src, "<<"); } - expect!(src, 2, |c| c != b' '); + expect!(src, 2, |c| c != b' ')?; - let end = until_while!(src, 2, b'>', |c| c != b'<' && c != b'\n'); + let end = until_while!(src, 2, b'>', |c| c != b'<' && c != b'\n')?; - expect!(src, end - 1, |c| c != b' '); + expect!(src, end - 1, |c| c != b' ')?; expect!(src, end + 1, b'>')?; Some((Target(&src[2..end]), end + 2)) diff --git a/src/utils.rs b/src/utils.rs index 826e157..c6fc278 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -3,13 +3,10 @@ #[macro_export] macro_rules! expect { ($src:ident, $index:expr, $expect:tt) => { - $src.as_bytes().get($index).filter(|&b| b == &$expect) + $src.as_bytes().get($index).filter(|&&b| b == $expect) }; ($src:ident, $index:expr, $expect:expr) => { - // $src.as_bytes().get($index).filter($expect) - if $index >= $src.len() || !$expect($src.as_bytes()[$index]) { - return None; - } + $src.as_bytes().get($index).filter(|&&b| $expect(b)) }; } @@ -30,30 +27,30 @@ macro_rules! eol { macro_rules! until { ($src:expr, $until:tt) => {{ let mut pos = 0; - while pos < $src.len() { - if $until == $src.as_bytes()[pos] { - break; + loop { + if pos >= $src.len() { + break None; + } + + if $until == $src.as_bytes()[pos] { + break Some(pos); + } else { + pos += 1; } - pos += 1; - } - if pos == $src.len() { - None - } else { - Some(pos) } }}; ($src:expr, $until:expr) => {{ let mut pos = 0; - while pos < $src.len() { - if $until($src.as_bytes()[pos]) { - break; + loop { + if pos >= $src.len() { + break None; + } + + if $until($src.as_bytes()[pos]) { + break Some(pos); + } else { + pos += 1; } - pos += 1; - } - if pos == $src.len() { - None - } else { - Some(pos) } }}; } @@ -62,41 +59,33 @@ macro_rules! until { macro_rules! until_while { ($src:expr, $start:expr, $until:tt, $while:expr) => {{ let mut pos = $start; - while pos < $src.len() { - // println!("pos {} char {} ", pos, $src.as_bytes()[pos] as char,); - if $until == $src.as_bytes()[pos] { - break; + loop { + if pos >= $src.len() { + break None; + } else if $until == $src.as_bytes()[pos] { + break Some(pos); } else if $while($src.as_bytes()[pos]) { pos += 1; continue; } else { - return None; + break None; } } - if pos == $src.len() { - return None; - } else { - pos - } }}; ($src:expr, $start:expr, $until:expr, $while:expr) => {{ let mut pos = $start; - while pos < $src.len() { - // println!("pos {} char {}", pos, $src.as_bytes()[pos] as char); - if $until($src.as_bytes()[pos]) { - break; + loop { + if pos >= $src.len() { + break None; + } else if $until($src.as_bytes()[pos]) { + break Some(pos); } else if $while($src.as_bytes()[pos]) { pos += 1; continue; } else { - return None; + break None; } } - if pos == $src.len() { - return None; - } else { - pos - } }}; } @@ -111,16 +100,6 @@ macro_rules! cond_eq { }; } -#[macro_export] -macro_rules! position { - ($s:ident, $i:expr, $p:expr) => { - match $s[$i..].chars().position($p) { - Some(x) => x + $i, - None => return None, - } - }; -} - #[macro_export] macro_rules! starts_with { ($s:ident, $p:expr) => { @@ -144,13 +123,13 @@ macro_rules! skip_space { macro_rules! skip_empty_line { ($src:ident, $from:expr) => {{ let mut pos = $from; - while pos < $src.len() { - if $src.as_bytes()[pos] != b'\n' { - break; + loop { + if pos >= $src.len() || $src.as_bytes()[pos] != b'\n' { + break pos; + } else { + pos += 1; } - pos += 1; } - pos }}; }