use std::sync::LazyLock;
use linkify::LinkFinder;
use url::Url;
pub(crate) fn parse_url_or_path(input: &str) -> Result<Url, &str> {
match Url::parse(input) {
Ok(url) if url.scheme().len() == 1 => Err(input),
Ok(url) => Ok(url),
_ => Err(input),
}
}
static LINK_FINDER: LazyLock<LinkFinder> = LazyLock::new(LinkFinder::new);
pub(crate) fn find_links(input: &str) -> impl Iterator<Item = linkify::Link<'_>> {
LINK_FINDER.links(input)
}
#[cfg(test)]
mod tests {
use super::*;
use rstest::rstest;
#[rstest]
#[case("tel:1", Ok("tel:1"))]
#[case("file:///a", Ok("file:///a"))]
#[case("http://a.com", Ok("http://a.com/"))]
#[case("", Err(""))]
#[case(".", Err("."))]
#[case("C:", Err("C:"))]
#[case("/unix", Err("/unix"))]
#[case("C:/a", Err("C:/a"))]
#[case(r"C:\a\b", Err(r"C:\a\b"))]
#[case("**/*.md", Err("**/*.md"))]
#[case("something", Err("something"))]
fn test_parse_url_or_path(#[case] input: &str, #[case] expected: Result<&str, &str>) {
let result = parse_url_or_path(input);
assert_eq!(
result.as_ref().map(Url::as_str),
expected.as_deref(),
"input={input:?}, expected={expected:?}"
);
}
}