use std::str::FromStr; use failure::Error; #[derive(Clone, Debug)] pub struct Repository { pub path: RepoPath, pub description: String } #[derive(Clone, Debug)] pub struct RepoPath { pub site: RepoSite, pub qual: RepoQualifier, pub name: RepoName } impl RepoPath { pub fn from_parts(site: &str, qual: &str, name: &str) -> Result { Ok(RepoPath { site: site.parse()?, qual: qual.parse()?, name: name.parse()? }) } } #[derive(Clone, Copy, Debug)] pub enum RepoSite { Github } impl RepoSite { pub fn to_base_uri(&self) -> &'static str { match self { &RepoSite::Github => "https://github.com" } } } impl FromStr for RepoSite { type Err = Error; fn from_str(input: &str) -> Result { match input { "github" => Ok(RepoSite::Github), _ => Err(format_err!("unknown repo site identifier")) } } } impl AsRef for RepoSite { fn as_ref(&self) -> &str { match self { &RepoSite::Github => "github" } } } #[derive(Clone, Debug)] pub struct RepoQualifier(String); impl FromStr for RepoQualifier { type Err = Error; fn from_str(input: &str) -> Result { let is_valid = input.chars().all(|c| { c.is_ascii_alphanumeric() || c == '.' || c == '-' || c == '_' }); ensure!(is_valid, "invalid repo qualifier"); Ok(RepoQualifier(input.to_string())) } } impl AsRef for RepoQualifier { fn as_ref(&self) -> &str { self.0.as_ref() } } #[derive(Clone, Debug)] pub struct RepoName(String); impl FromStr for RepoName { type Err = Error; fn from_str(input: &str) -> Result { let is_valid = input.chars().all(|c| { c.is_ascii_alphanumeric() || c == '.' || c == '-' || c == '_' }); ensure!(is_valid, "invalid repo name"); Ok(RepoName(input.to_string())) } } impl AsRef for RepoName { fn as_ref(&self) -> &str { self.0.as_ref() } }