use std::str::FromStr; use thiserror::Error; use url::Url; #[derive(Error, Debug)] pub enum ParseLinkError { #[error("Could not parse valid link")] InvalidLink, #[error("Unexpected host")] UnknownHostError, } #[derive(Debug)] pub enum Link { E621Post { post: u32 }, E621Pool { pool: u32 }, } impl FromStr for Link { type Err = ParseLinkError; fn from_str(s: &str) -> Result { let url = Url::from_str(s).map_err(|_| return ParseLinkError::InvalidLink)?; if let Some(domain) = url.domain() { match domain { "www.e621.net" | "e621.net" | "www.e926.net" | "e926.net" => { if let Some(mut path_segments) = url.path_segments() { let first_segment = path_segments.next(); if first_segment.is_none() { return Err(ParseLinkError::InvalidLink); } let first_segment = first_segment.unwrap(); let last_segment = path_segments.last(); if last_segment.is_none() { return Err(ParseLinkError::InvalidLink); } let last_segment = last_segment.unwrap(); match first_segment { "post" | "posts" => { if let Ok(post) = u32::from_str(last_segment) { return Ok(Link::E621Post { post }); } } "pools" => { if let Ok(pool) = u32::from_str(last_segment) { return Ok(Link::E621Pool { pool }); } } _ => { println!("e621 first segment: {first_segment}"); } } } return Err(ParseLinkError::UnknownHostError); } _ => { return Err(ParseLinkError::UnknownHostError); } } } else { return Err(ParseLinkError::UnknownHostError); } } }