lychee/src/uri.rs
Matthias a78e8318cd
Add (machine-readable) output file support (fixes #53)
For now we only support JSON.
I honestly don't know if it makes sense to include other formats.
For example, MD and HTML are not really
machine-readable. YAML is not
a great standard format for this use-case. Open for discussions, though.
2020-12-14 01:15:14 +01:00

89 lines
2.3 KiB
Rust

use anyhow::Result;
use serde::{Deserialize, Serialize};
use std::net::IpAddr;
use std::{convert::TryFrom, fmt::Display};
use url::Url;
/// Lychee's own representation of a URI, which encapsulates all support formats
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Uri {
/// Website URL
Website(Url),
/// Mail address
Mail(String),
}
impl Uri {
pub fn as_str(&self) -> &str {
match self {
Uri::Website(url) => url.as_str(),
Uri::Mail(address) => address.as_str(),
}
}
pub fn scheme(&self) -> Option<String> {
match self {
Uri::Website(url) => Some(url.scheme().to_string()),
Uri::Mail(_address) => None,
}
}
pub fn host_ip(&self) -> Option<IpAddr> {
match self {
Self::Website(url) => match url.host()? {
url::Host::Ipv4(v4_addr) => Some(v4_addr.into()),
url::Host::Ipv6(v6_addr) => Some(v6_addr.into()),
_ => None,
},
Self::Mail(_) => None,
}
}
}
impl TryFrom<&str> for Uri {
type Error = anyhow::Error;
fn try_from(s: &str) -> Result<Self> {
Ok(Uri::Website(Url::parse(s)?))
}
}
impl Display for Uri {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.as_str())
}
}
#[cfg(test)]
mod test {
use reqwest::Url;
use super::*;
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
#[test]
fn test_uri_host_ip_v4() {
let uri =
Uri::Website(Url::parse("http://127.0.0.1").expect("Expected URI with valid IPv4"));
let ip = uri.host_ip().expect("Expected a valid IPv4");
assert_eq!(ip, IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)));
}
#[test]
fn test_uri_host_ip_v6() {
let uri =
Uri::Website(Url::parse("https://[2020::0010]").expect("Expected URI with valid IPv6"));
let ip = uri.host_ip().expect("Expected a valid IPv6");
assert_eq!(
ip,
IpAddr::V6(Ipv6Addr::new(0x2020, 0, 0, 0, 0, 0, 0, 0x10))
);
}
#[test]
fn test_uri_host_ip_no_ip() {
let uri = Uri::Website(Url::parse("https://some.cryptic/url").expect("Expected valid URI"));
let ip = uri.host_ip();
assert!(ip.is_none());
}
}