Skip to content

Commit 96f7d64

Browse files
author
yggverse
committed
remove regex dependency, rename constructor, implement zero-copy trait
1 parent 7f3ea67 commit 96f7d64

File tree

3 files changed

+70
-19
lines changed

3 files changed

+70
-19
lines changed

src/line/code/inline.rs

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1+
pub mod gemtext;
2+
pub use gemtext::Gemtext;
3+
14
use super::TAG;
2-
use glib::{Regex, RegexCompileFlags, RegexMatchFlags};
35

46
/// Inline [preformatted](https://geminiprotocol.net/docs/gemtext-specification.gmi#in-pre-formatted-mode) entity holder
57
pub struct Inline {
@@ -10,24 +12,35 @@ impl Inline {
1012
// Constructors
1113

1214
/// Parse `Self` from line string
13-
pub fn from(line: &str) -> Option<Self> {
14-
// Skip next operations on prefix and postfix mismatch `TAG`
15-
// * replace regex implementation @TODO
16-
if !line.starts_with(TAG) && !line.ends_with(TAG) {
17-
return None;
18-
}
15+
pub fn parse(line: &str) -> Option<Self> {
16+
line.as_value().map(|v| Self {
17+
value: v.to_string(),
18+
})
19+
}
1920

20-
// Parse line
21-
let regex = Regex::split_simple(
22-
r"^`{3}([^`]+)`{3}$",
23-
line,
24-
RegexCompileFlags::DEFAULT,
25-
RegexMatchFlags::DEFAULT,
26-
);
21+
// Converters
2722

28-
// Extract formatted value
29-
Some(Self {
30-
value: regex.get(1)?.trim().to_string(),
31-
})
23+
/// Convert `Self` to [Gemtext](https://geminiprotocol.net/docs/gemtext-specification.gmi) line
24+
pub fn to_source(&self) -> String {
25+
self.value.to_source()
26+
}
27+
}
28+
29+
#[test]
30+
fn test() {
31+
fn assert(source: &str, value: &str) {
32+
let list = Inline::parse(source).unwrap();
33+
assert_eq!(list.value, value);
34+
assert_eq!(list.to_source(), format!("```{value}```"));
3235
}
36+
assert("```inline```", "inline");
37+
assert("```inline ```", "inline");
38+
assert("``` inline ```", "inline");
39+
assert("``` inline```", "inline");
40+
assert("``` inline``` ", "inline");
41+
assert("``````inline``` ", "```inline");
42+
assert("``````inline`````` ", "```inline```");
43+
assert("```inline`````` ", "inline```");
44+
assert!("```inline".as_value().is_none());
45+
assert!("```inline``` ne".as_value().is_none());
3346
}

src/line/code/inline/gemtext.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
use super::TAG;
2+
3+
pub trait Gemtext {
4+
/// Get [Gemtext](https://geminiprotocol.net/docs/gemtext-specification.gmi) value for `Self`
5+
fn as_value(&self) -> Option<&str>;
6+
/// Convert `Self` to [Gemtext](https://geminiprotocol.net/docs/gemtext-specification.gmi) line
7+
fn to_source(&self) -> String;
8+
}
9+
10+
impl Gemtext for str {
11+
fn as_value(&self) -> Option<&str> {
12+
if let Some(p) = self.strip_prefix(TAG) {
13+
return p.trim().strip_suffix(TAG).map(|s| s.trim());
14+
}
15+
None
16+
}
17+
fn to_source(&self) -> String {
18+
format!("{TAG}{}{TAG}", self.trim())
19+
}
20+
}
21+
22+
#[test]
23+
fn test() {
24+
fn assert(source: &str, value: &str) {
25+
assert_eq!(source.as_value(), Some(value));
26+
assert_eq!(value.to_source(), format!("```{value}```"));
27+
}
28+
assert("```inline```", "inline");
29+
assert("```inline ```", "inline");
30+
assert("``` inline ```", "inline");
31+
assert("``` inline```", "inline");
32+
assert("``` inline``` ", "inline");
33+
assert("``````inline``` ", "```inline");
34+
assert("``````inline`````` ", "```inline```");
35+
assert("```inline`````` ", "inline```");
36+
assert!("```inline".as_value().is_none());
37+
assert!("```inline``` ne".as_value().is_none());
38+
}

tests/integration.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ fn gemtext() {
3636
// Parse document by line
3737
for line in gemtext.lines() {
3838
// Inline code
39-
if let Some(result) = Inline::from(line) {
39+
if let Some(result) = Inline::parse(line) {
4040
code_inline.push(result);
4141
continue;
4242
}

0 commit comments

Comments
 (0)