#[derive(Hash,Eq,PartialEq)] pub struct RobloxAssetId(pub u64); #[derive(Debug)] #[allow(dead_code)] pub enum RobloxAssetIdParseErr{ Url(url::ParseError), UnknownScheme(String), ParseInt(std::num::ParseIntError), MissingAssetId(String), } impl std::str::FromStr for RobloxAssetId{ type Err=RobloxAssetIdParseErr; fn from_str(s:&str)->Result{ let url=url::Url::parse(s).map_err(RobloxAssetIdParseErr::Url)?; let parsed_asset_id=match url.scheme(){ "rbxassetid"=>url.domain().ok_or_else(||RobloxAssetIdParseErr::MissingAssetId(s.to_owned()))?.parse(), "http"|"https"=>{ let (_,asset_id)=url.query_pairs() .find(|(id,_)|match id.as_ref(){ "ID"|"id"|"Id"|"iD"=>true, _=>false, }).ok_or_else(||RobloxAssetIdParseErr::MissingAssetId(s.to_owned()))?; asset_id.parse() }, _=>Err(RobloxAssetIdParseErr::UnknownScheme(s.to_owned()))?, }; Ok(Self(parsed_asset_id.map_err(RobloxAssetIdParseErr::ParseInt)?)) } } impl std::fmt::Display for RobloxAssetIdParseErr{ fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{ write!(f,"{self:?}") } } impl std::error::Error for RobloxAssetIdParseErr{}