From c4dc0795041dcbfe97dc31fef970412395a3c48e Mon Sep 17 00:00:00 2001 From: David Zuelke Date: Tue, 16 Sep 2025 17:14:11 +0200 Subject: [PATCH] Implement TryFrom for url::Url GitUrl::url_compat_display() is currently private, but it would be very useful to have this functionality - in my case, normalizing an SSH style URL is fine, especially because I do not want to bother with handling the 'url lifetime of GitUrl in my wrapper enum. This change implements fallible conversion to url::Url for GitUrl and &GitUrl via url_compat_display(). Longer term it might be wise to re-visit the use of a lifetime for the purpose of re-using slices of the input string - the url::Url crate does not bother with such micro-optimizations either, presumably for good reasons. Obviously, to use a GitUrl as a url::Url, the conversion to url::Url still has to happen twice (because GitUrl::parse() incurs the conversion via GitUrl::is_valid()), but that can be optimized in a separate change (e.g. via a new GitUrl::parse_to_url(), or by removing the conversion from is_valid() altogether, leaving it to the caller to attempt the conversion). --- src/types/mod.rs | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/types/mod.rs b/src/types/mod.rs index a5e8750..0dcbbf0 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -12,6 +12,7 @@ pub use error::GitUrlParseError; use core::str; use std::fmt; +use url::Url; use getset::{CloneGetters, CopyGetters, Setters}; #[cfg(feature = "log")] @@ -140,6 +141,24 @@ impl<'url> GitUrl<'url> { } } +#[cfg(feature = "url")] +impl<'url> TryFrom<&GitUrl<'url>> for Url { + type Error = url::ParseError; + fn try_from(value: &GitUrl) -> Result { + // Since we don't fully implement any spec, we'll rely on the url crate + Url::parse(&value.url_compat_display()) + } +} + +#[cfg(feature = "url")] +impl<'url> TryFrom> for Url { + type Error = url::ParseError; + fn try_from(value: GitUrl) -> Result { + // Since we don't fully implement any spec, we'll rely on the url crate + Url::parse(&value.url_compat_display()) + } +} + impl<'url> GitUrl<'url> { /// Returns `GitUrl` after removing all user info values pub fn trim_auth(&self) -> GitUrl { @@ -325,7 +344,7 @@ impl<'url> GitUrl<'url> { #[cfg(feature = "url")] { // Since we don't fully implement any spec, we'll rely on the url crate - let _u = url::Url::parse(&self.url_compat_display())?; + let _u: Url = self.try_into()?; } Ok(())