use anyhow::{Result, bail}; use std::{path::PathBuf, str::FromStr}; use url::Url; pub enum Source { Path(PathBuf), Url(Url), } impl Source { pub fn from_str(source: &str) -> Result { Ok(if source.contains("://") { Self::Url(Url::from_str(source)?) } else { Self::Path(PathBuf::from_str(source)?.canonicalize()?) }) } pub async fn get(&self) -> Result { Ok(match self { Source::Path(path) => tokio::fs::read_to_string(path).await?, Source::Url(url) => { let request = url.as_str(); let response = reqwest::get(request).await?; let status = response.status(); if status.is_success() { response.text().await? } else { bail!("Could not receive remote list `{request}`: `{status}`") } } }) } } impl FromStr for Source { type Err = anyhow::Error; fn from_str(s: &str) -> Result { Source::from_str(s) } } impl std::fmt::Display for Source { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::Path(path) => write!(f, "{}", path.to_string_lossy()), Self::Url(url) => write!(f, "{url}"), } } }