use serde::{Deserialize, Serialize};
use std::fmt::Display;
use thiserror::Error;
use url::Url;
use super::hosting_type::HostingType;
#[derive(Debug, Error)]
pub enum ParseError {
#[error("Failed to parse as URL: {0}")]
UrlParseError(#[from] url::ParseError),
#[error("URL is missing a host part: '{0}'")]
MissingHost(String),
#[error("Unrecognized hosting provider host '{1}' in project URL '{0}'")]
UnrecognizedHost(String, String),
}
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
pub enum HostingProviderId {
#[default]
Inapplicable,
AppropediaOrg,
CodebergOrg,
GitHubCom,
GitLabCom,
OshwaOrg,
ThingiverseCom,
}
impl HostingProviderId {
#[must_use]
pub const fn as_str(self) -> &'static str {
match self {
Self::Inapplicable => "N/A",
Self::AppropediaOrg => "appropedia.org",
Self::CodebergOrg => "codeberg.org",
Self::GitHubCom => "github.com",
Self::GitLabCom => "gitlab.com",
Self::ThingiverseCom => "thingiverse.com",
Self::OshwaOrg => "oshwa.org",
}
}
pub fn from_url(url: &str) -> Result<Self, ParseError> {
let parsed_url = Url::parse(url)?;
let host = parsed_url
.host()
.ok_or_else(|| ParseError::MissingHost(url.to_string()))?;
let host_str = host.to_string().to_lowercase();
match host_str.as_str() {
"appropedia.org" | "www.appropedia.org" => Ok(Self::AppropediaOrg),
"codeberg.org" => Ok(Self::CodebergOrg),
"github.com" | "raw.githubusercontent.com" => Ok(Self::GitHubCom),
"gitlab.com" => Ok(Self::GitLabCom),
"oshwa.org" | "certification.oshwa.org" => Ok(Self::OshwaOrg),
"thingiverse.com" | "www.thingiverse.com" => Ok(Self::ThingiverseCom),
_ => Err(ParseError::UnrecognizedHost(url.to_string(), host_str)),
}
}
#[must_use]
pub const fn r#type(self) -> HostingType {
match self {
Self::Inapplicable => HostingType::ManifestsRepo, Self::AppropediaOrg => HostingType::Appropedia,
Self::CodebergOrg => HostingType::ForgeJo,
Self::GitHubCom => HostingType::GitHub,
Self::GitLabCom => HostingType::GitLab,
Self::ThingiverseCom => HostingType::Thingiverse,
Self::OshwaOrg => HostingType::Oshwa,
}
}
}
impl AsRef<str> for HostingProviderId {
fn as_ref(&self) -> &'static str {
self.as_str()
}
}
impl Display for HostingProviderId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(self.as_str())
}
}