From 4ce1b20bf7282cf5dc38ec458a0326656e772633 Mon Sep 17 00:00:00 2001 From: yggverse Date: Sun, 16 Mar 2025 13:42:23 +0200 Subject: [PATCH] rename constructor, implement zero-copy trait, remove extra regex parser --- src/line/list.rs | 54 +++++++++++++++++++++++++++++++++----------- tests/integration.rs | 2 +- 2 files changed, 42 insertions(+), 14 deletions(-) diff --git a/src/line/list.rs b/src/line/list.rs index d9959f2..7d22f9b 100644 --- a/src/line/list.rs +++ b/src/line/list.rs @@ -1,4 +1,5 @@ -use glib::{Regex, RegexCompileFlags, RegexMatchFlags}; +/// [List item](https://geminiprotocol.net/docs/gemtext-specification.gmi#list-items) tag +pub const TAG: char = '*'; /// [List](https://geminiprotocol.net/docs/gemtext-specification.gmi#list-items) entity holder pub struct List { @@ -8,19 +9,46 @@ pub struct List { impl List { // Constructors - /// Parse `Self` from line string - pub fn from(line: &str) -> Option { - // Parse line - let regex = Regex::split_simple( - r"^\*\s*(.*)$", - line, - RegexCompileFlags::DEFAULT, - RegexMatchFlags::DEFAULT, - ); - - // Extract formatted value + /// Parse `Self` from [Gemtext](https://geminiprotocol.net/docs/gemtext-specification.gmi) line + pub fn parse(line: &str) -> Option { Some(Self { - value: regex.get(1)?.trim().to_string(), + value: line.as_value()?.to_string(), }) } + + // Converters + + /// Convert `Self` to [Gemtext](https://geminiprotocol.net/docs/gemtext-specification.gmi) line + pub fn as_source(&self) -> String { + self.value.to_source() + } +} + +pub trait Gemtext { + /// Get [Gemtext](https://geminiprotocol.net/docs/gemtext-specification.gmi) value from `Self` + fn as_value(&self) -> Option<&Self>; + /// Convert `Self` to [Gemtext](https://geminiprotocol.net/docs/gemtext-specification.gmi) line + fn to_source(&self) -> String; +} + +impl Gemtext for str { + fn as_value(&self) -> Option<&Self> { + self.strip_prefix(TAG).map(|s| s.trim()) + } + fn to_source(&self) -> String { + format!("{TAG} {}", self.trim()) + } +} + +#[test] +fn test() { + const SOURCE: &str = "* Item"; + const VALUE: &str = "Item"; + + // test struct + assert_eq!(List::parse(SOURCE).unwrap().value, VALUE); + + // test trait + assert_eq!(SOURCE.as_value(), Some(VALUE)); + assert_eq!(VALUE.to_source(), SOURCE) } diff --git a/tests/integration.rs b/tests/integration.rs index 6c28f35..2b4731b 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -72,7 +72,7 @@ fn gemtext() { } // List - if let Some(result) = List::from(line) { + if let Some(result) = List::parse(line) { list.push(result); continue; }