use std::{fmt, str::FromStr};
use onetaskgraph_plugin_api::SourcePlugin;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
#[serde(into = "String", try_from = "String")]
pub enum PluginKind {
GithubProjects,
InMemory,
Linear,
LocalMd,
Subprocess,
}
impl PluginKind {
pub const ALL: [Self; 5] = [
Self::GithubProjects,
Self::InMemory,
Self::Linear,
Self::LocalMd,
Self::Subprocess,
];
#[must_use]
pub fn as_str(self) -> &'static str {
match self {
Self::GithubProjects => "github-projects",
Self::InMemory => "in-memory",
Self::Linear => "linear",
Self::LocalMd => "local-md",
Self::Subprocess => "subprocess",
}
}
#[must_use]
pub fn parse(name: &str) -> Option<Self> {
Self::ALL.into_iter().find(|kind| kind.as_str() == name)
}
#[must_use]
pub fn plugin(self) -> Box<dyn SourcePlugin> {
match self {
Self::GithubProjects => Box::new(onetaskgraph_github_projects::Plugin),
Self::InMemory => Box::new(onetaskgraph_in_memory::Plugin),
Self::Linear => Box::new(onetaskgraph_linear::Plugin),
Self::LocalMd => Box::new(onetaskgraph_local_md::Plugin),
Self::Subprocess => Box::new(crate::subprocess::SubprocessPlugin),
}
}
}
impl TryFrom<String> for PluginKind {
type Error = String;
fn try_from(value: String) -> Result<Self, Self::Error> {
Self::parse(&value).ok_or_else(|| {
format!(
"no plugin of this build is called {value:?}; it knows {}",
plugin_kinds().join(", ")
)
})
}
}
impl From<PluginKind> for String {
fn from(value: PluginKind) -> Self {
value.as_str().to_owned()
}
}
impl fmt::Display for PluginKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_str())
}
}
impl FromStr for PluginKind {
type Err = String;
fn from_str(value: &str) -> Result<Self, Self::Err> {
value.to_owned().try_into()
}
}
#[must_use]
pub fn registry() -> Vec<Box<dyn SourcePlugin>> {
PluginKind::ALL.map(PluginKind::plugin).into()
}
#[must_use]
pub fn plugin_kinds() -> Vec<&'static str> {
registry().iter().map(|plugin| plugin.kind()).collect()
}
#[must_use]
pub fn plugin_for(kind: &str) -> Option<Box<dyn SourcePlugin>> {
PluginKind::parse(kind).map(PluginKind::plugin)
}